runhttpd: hostenv
build/hostenv.sh $(realpath host) $(LUA_MODULEDIR) $(LUA_LIBRARYDIR) "$(realpath host/usr/bin/lucittpd) $(realpath host)/usr/lib/lucittpd/plugins"
-runluci: luahost
- build/hostenv.sh $(realpath host) $(LUA_MODULEDIR) $(LUA_LIBRARYDIR) "$(realpath libs/httpd/host/runluci) $(realpath host) $(HTDOCS)"
+runluci: runhttpd
runlua: hostenv
build/hostenv.sh $(realpath host) $(LUA_MODULEDIR) $(LUA_LIBRARYDIR) lua
#!/usr/bin/lua
-require("socket")
-require("luci.ip")
-require("luci.model.uci")
+local nixio = require "nixio"
+local server = nixio.bind(nil, arg[1] or 8082)
+local stat = server:listen(32)
-local uci = luci.model.uci.cursor_state()
-uci:load("network")
-
-local server = socket.bind("0.0.0.0", arg[1] or 8082)
-server:settimeout(0, "t")
-
-while true do
+while stat do
local client = server:accept()
if client then
- client:settimeout(1)
- local srv
- local ip = luci.ip.IPv4((client:getpeername()))
-
- local function find_srv(section)
- if section.ipaddr then
- local net = luci.ip.IPv4(section.ipaddr, section.netmask)
- if ip and net and net:contains(ip) then
- srv = section.ipaddr
- return
- end
- end
- end
-
- uci:foreach("network", "interface", find_srv)
- uci:foreach("network", "alias", find_srv)
+ client:setopt("socket", "rcvtimeo", 1)
+ client:setopt("socket", "sndtimeo", 1)
+ local srv = client:getsockname()
- client:receive()
- client:send("HTTP/1.0 302 Found\r\nLocation: http://" .. srv ..
+ client:read(1024)
+ client:writeall("HTTP/1.0 302 Found\r\nLocation: http://" .. srv ..
(arg[2] or "/luci/splash") .. "\r\n\r\n")
client:close()
- else
- socket.sleep(0.1)
end
end
+++ /dev/null
-include ../../build/config.mk
-include ../../build/gccconfig.mk
-
-LPEG_VERSION = 0.8.1
-LPEG_SITE = http://www.inf.puc-rio.br/~roberto/lpeg
-LPEG_DIR = lpeg-$(LPEG_VERSION)
-LPEG_FILE = $(LPEG_DIR).tar.gz
-LPEG_URL = $(LPEG_SITE)/$(LPEG_FILE)
-
-all: compile
-
-include ../../build/module.mk
-
-$(LPEG_FILE):
- wget -O $@ $(LPEG_URL) || rm -f $@
-
-$(LPEG_DIR)/.prepared: $(LPEG_FILE)
- rm -rf $(LPEG_DIR)
- tar xvfz $(LPEG_FILE)
- touch $@
-
-compile: $(LPEG_DIR)/.prepared
- $(MAKE) -C $(LPEG_DIR) CC=$(CC) COPT="$(CFLAGS) $(LUA_CFLAGS) -fpic"
- mkdir -p dist$(LUA_LIBRARYDIR)
- cp $(LPEG_DIR)/{lpeg.so,re.lua} dist$(LUA_LIBRARYDIR)
-
-luasource:
-luastrip:
-luacompile:
-compile-all: compile
-
-clean:
- rm -rf $(LPEG_DIR) $(LPEG_FILE)
+++ /dev/null
-luasocket-*
+++ /dev/null
-include ../../build/config.mk
-include ../../build/gccconfig.mk
-
-LUASOCKET_VERSION = 2.0.2
-LUASOCKET_SITE = http://dev.luci.freifunk-halle.net/sources/
-LUASOCKET_DIR = luasocket-$(LUASOCKET_VERSION)
-LUASOCKET_FILE = $(LUASOCKET_DIR).tar.gz
-LUASOCKET_URL = $(LUASOCKET_SITE)/$(LUASOCKET_FILE)
-INSTALL_MODULEDIR = dist$(LUA_MODULEDIR)
-INSTALL_LIBRARYDIR = dist$(LUA_LIBRARYDIR)
-
-all: compile
-
-include ../../build/module.mk
-
-$(LUASOCKET_FILE):
- wget -O $@ $(LUASOCKET_URL) || rm -f $@
-
-$(LUASOCKET_DIR)/.prepared: $(LUASOCKET_FILE)
- rm -rf $(LUASOCKET_DIR)
- tar xvfz $(LUASOCKET_FILE)
- touch $@
-
-compile: $(LUASOCKET_DIR)/.prepared
- $(MAKE) -C $(LUASOCKET_DIR) CC=$(CC) CFLAGS="$(CFLAGS) $(LUA_CFLAGS) $(FPIC)" LDFLAGS="$(LDFLAGS) $(LUA_SHLIBS) $(SHLIB_FLAGS)" OS="$(OS)"
- mkdir -p $(INSTALL_LIBRARYDIR) $(INSTALL_MODULEDIR)
- $(MAKE) -C $(LUASOCKET_DIR) install INSTALL_TOP_SHARE=../../$(INSTALL_MODULEDIR) INSTALL_TOP_LIB=../../$(INSTALL_LIBRARYDIR)
-
-compile-all: compile
-
-clean:
- rm -rf $(LUASOCKET_DIR) $(LUASOCKET_FILE)
+++ /dev/null
-# Copyright (C) 2008 OpenWrt.org
-#
-# This is free software, licensed under the GNU General Public License v2.
-# See /LICENSE for more information.
-#
-# $Id$
-
-include $(TOPDIR)/rules.mk
-
-PKG_NAME:=lpeg
-PKG_VERSION:=0.8.1
-PKG_RELEASE:=1
-
-PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
-PKG_SOURCE_URL:=http://www.inf.puc-rio.br/~roberto/lpeg
-PKG_MD5SUM:=b6b172bbcdcba5c87b37eef9bb5ae199
-
-PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
-PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
-
-include $(INCLUDE_DIR)/package.mk
-
-define Package/lpeg
- SECTION:=lang
- CATEGORY:=Languages
- SUBMENU:=LUA
- TITLE:=LPEG - Parsing Expression Grammars
- URL:=http://www.inf.puc-rio.br/~roberto/lpeg.html
- DEPENDS:=+liblua
-endef
-
-MAKE_FLAGS += COPT="$(TARGET_CFLAGS) $(FPIC) -I$(STAGING_DIR)/usr/include"
-
-define Build/Configure
-endef
-
-define Package/lpeg/install
- $(INSTALL_DIR) $(1)/usr/lib/lua
- $(CP) $(PKG_BUILD_DIR)/{lpeg.so,re.lua} $(1)/usr/lib/lua
-endef
-
-$(eval $(call BuildPackage,lpeg))
+++ /dev/null
-include $(TOPDIR)/rules.mk
-
-PKG_NAME:=luasocket
-PKG_VERSION:=2.0.2
-PKG_RELEASE:=1
-
-PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
-PKG_SOURCE_URL:=http://dev.luci.freifunk-halle.net/sources/\
- http://luaforge.net/frs/download.php/2664/
-PKG_MD5SUM:=41445b138deb7bcfe97bff957503da8e
-
-PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
-PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
-
-include $(INCLUDE_DIR)/package.mk
-
-define Package/luasocket
- SECTION:=lang
- CATEGORY:=Languages
- SUBMENU:=LUA
- TITLE:=Socket support for Lua
- URL:=http://luaforge.net/projects/luasockets/
- DEPENDS:=+liblua
-endef
-
-define Build/Configure
-endef
-
-define Build/Compile
- for i in $(PKG_BUILD_DIR)/src/*.lua; do luac -s -o $$$$i $$$$i; done
- $(call Build/Compile/Default)
-endef
-
-MAKE_FLAGS += LD="$(TARGET_CC)" CFLAGS="$(TARGET_CFLAGS) -I$(STAGING_DIR)/usr/include -pedantic -Wall -fpic" LDFLAGS="$(TARGET_LDFLAGS) -shared -fpic"
-
-define Package/luasocket/install
- $(MAKE) -C$(PKG_BUILD_DIR) install INSTALL_TOP_SHARE=$(1)/usr/lib/lua INSTALL_TOP_LIB=$(1)/usr/lib/lua
-endef
-
-$(eval $(call BuildPackage,luasocket))
define Package/luci-app-splash
$(call Package/luci/fftemplate)
- DEPENDS+=+PACKAGE_luci-app-splash:luasocket
+ DEPENDS+=+PACKAGE_luci-app-splash:luci-nixio
TITLE:=Freifunk DHCP-Splash application
endef
+++ /dev/null
-include ../../build/config.mk
-include ../../build/module.mk
+++ /dev/null
-#!/usr/bin/env lua
-require("luci.httpd")
-require("luci.httpd.server")
-require("luci.httpd.handler.file")
-require("luci.httpd.handler.luci")
-
-SYSROOT = arg[1]
-DOCROOT = SYSROOT .. arg[2]
-PORT = 8080
-
-collectgarbage("setpause", 150)
-
-serversocket = luci.httpd.Socket("0.0.0.0", PORT)
-
-server = luci.httpd.server.Server()
-vhost = luci.httpd.server.VHost()
-
-server:set_default_vhost(vhost)
-
-pcall(function()
- require "uci"
- require "luci.model.uci".cursor = function(config, save)
- return uci.cursor(config or SYSROOT .. "/etc/config", save or SYSROOT .. "/tmp/.uci")
- end
-
- local x = require "luci.uvl".UVL.__init__
- require "luci.uvl".UVL.__init__ = function(self, schemedir)
- x(self, schemedir or SYSROOT .. "/lib/uci/schema")
- end
-end)
-
-require("luci.sys")
-luci.sys.user.checkpasswd = function() return true end
-
-
-filehandler = luci.httpd.handler.file.Simple(DOCROOT)
-vhost:set_default_handler(filehandler)
-
-lucihandler = luci.httpd.handler.luci.Luci()
-vhost:set_handler("/luci", lucihandler)
-
-io.stderr:write("Starting LuCI HTTPD on port " .. PORT .. "...\n")
-io.stderr:write("Point your browser to http://localhost:" .. PORT .. "/luci\n")
-
---daemon = luci.httpd.Daemon()
---daemon.debug = true
-luci.httpd.register(serversocket, server:create_daemon_handlers())
-luci.httpd.run()
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="refresh" content="0; URL=/luci" />
-</head>
-<body style="background-color: black">
-<a style="color: white; text-decoration: none" href="/luci">LuCI - Lua Configuration Interface</a>
-</body>
-</html>
+++ /dev/null
---[[
-
-HTTP server implementation for LuCI - core
-(c) 2008 Freifunk Leipzig / Jo-Philipp Wich <xm@leipzig.freifunk.net>
-(c) 2008 Steven Barth <steven@midlink.org>
-
-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", package.seeall)
-require("socket")
-
-THREAD_IDLEWAIT = 0.01
-THREAD_TIMEOUT = 90
-THREAD_LIMIT = nil
-
-local reading = {}
-local clhandler = {}
-local erhandler = {}
-
-local threadc = 0
-local threads = {}
-local threadm = {}
-local threadi = {}
-
-local _meta = {__mode = "k"}
-setmetatable(threadm, _meta)
-setmetatable(threadi, _meta)
-
-
-function Socket(ip, port)
- local sock, err = socket.bind( ip, port )
-
- if sock then
- sock:settimeout( 0, "t" )
- end
-
- return sock, err
-end
-
-function corecv(socket, ...)
- threadi[socket] = true
-
- while true do
- local chunk, err, part = socket:receive(...)
-
- if err ~= "timeout" then
- threadi[socket] = false
- return chunk, err, part
- end
-
- coroutine.yield()
- end
-end
-
-function cosend(socket, chunk, i, ...)
- threadi[socket] = true
- i = i or 1
-
- while true do
- local stat, err, sent = socket:send(chunk, i, ...)
-
- if err ~= "timeout" then
- threadi[socket] = false
- return stat, err, sent
- else
- i = sent and (sent + 1) or i
- end
-
- coroutine.yield()
- end
-end
-
-function register(socket, s_clhandler, s_errhandler)
- table.insert(reading, socket)
- clhandler[socket] = s_clhandler
- erhandler[socket] = s_errhandler
-end
-
-function run()
- while true do
- step()
- end
-end
-
-function step()
- local idle = true
- if not THREAD_LIMIT or threadc < THREAD_LIMIT then
- local now = os.time()
- for i, server in ipairs(reading) do
- local client = server:accept()
- if client then
- threadm[client] = now
- threadc = threadc + 1
- threads[client] = coroutine.create(clhandler[server])
- end
- end
- end
-
- for client, thread in pairs(threads) do
- coroutine.resume(thread, client)
- local now = os.time()
- if coroutine.status(thread) == "dead" then
- threadc = threadc - 1
- threads[client] = nil
- elseif threadm[client] and threadm[client] + THREAD_TIMEOUT < now then
- threads[client] = nil
- threadc = threadc - 1
- client:close()
- elseif not threadi[client] then
- threadm[client] = now
- idle = false
- end
- end
-
- if idle then
- socket.sleep(THREAD_IDLEWAIT)
- end
-end
+++ /dev/null
---[[
-
-HTTP server implementation for LuCI - file handler
-(c) 2008 Steven Barth <steven@midlink.org>
-(c) 2008 Freifunk Leipzig / Jo-Philipp Wich <xm@leipzig.freifunk.net>
-
-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")
-local ltn12 = require("luci.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.proto = luci.http.protocol
- 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( self.proto.urldecode( request.env.PATH_INFO, true ) )
-
- 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
- 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
- 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 duri = self.proto.urldecode( ruri, true )
- 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 .. "/" .. duri .. "/" .. candidate
- )
-
- if istat ~= nil and istat.type == "regular" then
- return Response( 301, {
- ["Location"] = ruri .. "/" .. candidate
- } ), ltn12.source.empty()
- end
- end
-
-
- local html = string.format(
- '<?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' ..
- '<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
- )
-
- local entries = luci.fs.dir( file )
-
- if type(entries) == "table" 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 />' ..
- '<small>Changed: %s</small></li>',
- 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 />' ..
- '<small>Size: %i Bytes | ' ..
- 'Changed: %s</small></li>',
- ruri, self.proto.urlencode( e ), e,
- self.mime.to_mime( e ),
- estat.size, self.date.to_http( estat.mtime )
- )
- end
- end
- end
-
- html = html .. '</ul><hr /></body></html>'
-
- return Response(
- 200, {
- ["Date"] = self.date.to_http( os.time() );
- ["Content-Type"] = "text/html; charset=ISO-8859-15";
- }
- ), ltn12.source.string(html)
- else
- return self:failure(403, "Permission denied")
- end
- 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
+++ /dev/null
---[[
-
-HTTP server implementation for LuCI - luci handler
-(c) 2008 Steven Barth <steven@midlink.org>
-
-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.luci", package.seeall)
-
-require("luci.dispatcher")
-require("luci.http")
-require("luci.http.protocol.date")
-local ltn12 = require("luci.ltn12")
-
-Luci = luci.util.class(luci.httpd.module.Handler)
-Response = luci.httpd.module.Response
-
-function Luci.__init__(self, limit)
- luci.httpd.module.Handler.__init__(self)
- self.limit = limit or 5
- self.running = {}
- setmetatable(self.running, {__mode = "k"})
-end
-
-function Luci.handle_head(self, ...)
- local response, sourceout = self:handle_get(...)
- return response
-end
-
-function Luci.handle_post(self, ...)
- return self:handle_get(...)
-end
-
-function Luci.handle_get(self, request, sourcein, sinkerr)
- local r = luci.http.Request(
- request.env,
- sourcein,
- sinkerr
- )
-
- local res, id, data1, data2 = true, 0, nil, nil
- local headers = {}
- local status = 200
- local active = true
-
- local x = coroutine.create(luci.dispatcher.httpdispatch)
- while not id or id < 3 do
- coroutine.yield()
-
- res, id, data1, data2 = coroutine.resume(x, r)
-
- if not res then
- status = 500
- headers["Content-Type"] = "text/plain"
- local err = {id}
- return Response( status, headers ), function() return table.remove(err) end
- end
-
- if id == 1 then
- status = data1
- elseif id == 2 then
- headers[data1] = data2
- end
- end
-
- local function iter()
- local res, id, data = coroutine.resume(x)
- if not res then
- return nil, id
- elseif not id or not active then
- return true
- elseif id == 5 then
- active = false
-
- while (coroutine.resume(x)) do
- end
-
- return nil
- elseif id == 4 then
- return data
- end
- if coroutine.status(x) == "dead" then
- return nil
- end
- end
-
- return Response(status, headers), iter
-end
+++ /dev/null
---[[
-LuCI - Lua Configuration Interface
-
-Copyright 2008 Steven Barth <steven@midlink.org>
-
-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.module", package.seeall)
-require("luci.util")
-require("luci.http.protocol")
-local ltn12 = require("luci.ltn12")
-
-
-
--- Server handler implementation
-Handler = luci.util.class()
-
--- Constructor
-function Handler.__init__(self)
- self.filters = {}
- self.handler = {}
-end
-
-
--- Adds a filter to the filter chain
-function Handler.addfilter(self, filter)
- table.insert(self.filters, filter)
-end
-
-
--- Creates a failure reply
-function Handler.failure(self, code, message)
- local response = Response(code, { ["Content-Type"] = "text/plain" })
- local sourceout = ltn12.source.string(message)
-
- return response, sourceout
-end
-
--- Processes a request
-function Handler.process(self, request, sourcein, sinkerr, ...)
- local stat, response, sourceout
-
- -- Process incoming filters
- for i, f in ipairs(self.filters) do
- local i = f:get("input")
-
- if i then
- sourcein = ltn12.source.chain(sourcein, i)
- end
-
- if f.request then
- f:request(request)
- end
- end
-
- -- Detect request Method
- local hname = "handle_" .. request.request_method
- if self[hname] then
- -- Run the handler
- stat, response, sourceout = luci.util.copcall(
- self[hname], self, request, sourcein, sinkerr, ...
- )
-
- -- Check for any errors
- if not stat then
- response, sourceout = self:failure(500, response)
- end
- else
- response, sourceout = self:failure(405, luci.http.protocol.statusmsg[405])
- end
-
- -- Check data
- if not luci.util.instanceof(response, Response) then
- response, sourceout = self:failure(500, "Core error: Invalid module response!")
- end
-
- -- Process outgoing filters
- for i, f in ipairs(self.filters) do
- local o = f:get("output")
-
- if o then
- sourceout = ltn12.source.chain(sourceout, o)
- end
-
- if f.response then
- f:response(response)
- end
- end
-
- return response, sourceout
-end
-
-
-
--- Server Filter implementation
-Filter = luci.util.class()
-
-function Filter.get(self, name)
- return self[name] and function(...) return self[name](self, ...) end
-end
-
--- Filters the incoming body stream
--- abstract function Filter.input(chunk)
-
--- Filters the outgoing body stream
--- abstract function Filter.output(chunk)
-
--- Filters the request object
--- abstract function Filter.request(request)
-
--- Filters the response object
--- abstract function Filter.response(response)
-
-
-
--- Handler Response
-Response = luci.util.class()
-
-function Response.__init__(self, status, headers)
- self.status = tonumber(status) or 200
- self.headers = (type(headers) == "table") and headers or {}
-end
-
-function Response.addheader(self, key, value)
- self.headers[key] = value
-end
-
-function Response.setstatus(self, status)
- self.status = status
-end
+++ /dev/null
---[[
-
-HTTP server implementation for LuCI - helper class
-(c) 2008 Freifunk Leipzig / Jo-Philipp Wich <xm@leipzig.freifunk.net>
-(c) 2008 Steven Barth <steven@midlink.org>
-
-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.server", package.seeall)
-require("socket")
-require("socket.http")
-require("luci.util")
-
-READ_BUFSIZE = 1024
-VERSION = 0.2
-
-
-VHost = luci.util.class()
-
-function VHost.__init__(self, handler)
- self.handler = handler
- self.dhandler = {}
-end
-
-function VHost.process(self, request, sourcein, sinkerr, ...)
- local handler = self.handler
-
- local uri = request.env.REQUEST_URI:match("^([^?]*)")
-
- -- SCRIPT_NAME
- request.env.SCRIPT_NAME = ""
-
- -- Call URI part
- request.env.PATH_INFO = uri
-
- for k, dhandler in pairs(self.dhandler) do
- if k == uri or k.."/" == uri:sub(1, #k+1) then
- handler = dhandler
- request.env.SCRIPT_NAME = k
- request.env.PATH_INFO = uri:sub(#k+1)
- break;
- end
- end
-
- if handler then
- return handler:process(request, sourcein, sinkerr, ...)
- end
-end
-
-
-function VHost.set_default_handler(self, handler)
- self.handler = handler
-end
-
-
-function VHost.set_handler(self, match, handler)
- self.dhandler[match] = handler
-end
-
-
-
-Server = luci.util.class()
-
-function Server.__init__(self, host)
- self.host = host
- self.vhosts = {}
-end
-
-function Server.set_default_vhost(self, vhost)
- self.host = vhost
-end
-
--- Sets a vhost
-function Server.set_vhost(self, name, vhost)
- self.vhosts[name] = vhost
-end
-
-function Server.create_daemon_handlers(self)
- return function(...) return self:process(...) end,
- function(...) return self:error_overload(...) end
-end
-
-
-function Server.error(self, socket, code, msg)
- hcode = tostring(code)
-
- socket:send( "HTTP/1.0 " .. hcode .. " " ..
- luci.http.protocol.statusmsg[code] .. "\r\n" )
- socket:send( "Connection: close\r\n" )
- socket:send( "Content-Type: text/plain\r\n\r\n" )
-
- if msg then
- socket:send( "HTTP-Error " .. code .. ": " .. msg .. "\r\n" )
- end
-end
-
-function Server.error_overload(self, socket)
- self:error(socket, 503, "Too many simultaneous connections")
-end
-
-
-function Server.process( self, client )
-
- -- Setup sockets and sources
- local thread = {
- receive = function(self, ...) return luci.httpd.corecv(client, ...) end,
- send = function(self, ...) return luci.httpd.cosend(client, ...) end,
- close = function(self, ...) return client:close(...) end,
- getfd = function(self, ...) return client:getfd(...) end,
- dirty = function(self, ...) return client:dirty(...) end
- }
-
- client:settimeout( 0 )
-
- local sourcein = ltn12.source.empty()
- local sourcehdr = luci.http.protocol.header_source( thread )
- local sinkerr = ltn12.sink.file( io.stderr )
-
- local close = false
-
- local reading = { client }
-
- local message, err
-
- repeat
- -- parse headers
- message, err = luci.http.protocol.parse_message_header( sourcehdr )
-
- if not message then
- self:error( thread, 400, err )
- break
- end
-
- -- keep-alive
- if message.http_version == 1.1 then
- close = (message.env.HTTP_CONNECTION == "close")
- else
- close = not message.env.HTTP_CONNECTION or message.env.HTTP_CONNECTION == "close"
- end
-
- if message.request_method == "get" or message.request_method == "head" then
- -- Be happy
-
- elseif message.request_method == "post" then
- -- If we have a HTTP/1.1 client and an Expect: 100-continue header then
- -- respond with HTTP 100 Continue message
- if message.http_version == 1.1 and message.headers['Expect'] and
- message.headers['Expect'] == '100-continue'
- then
- thread:send("HTTP/1.1 100 Continue\r\n\r\n")
- end
-
- if message.headers['Transfer-Encoding'] and
- message.headers['Transfer-Encoding'] ~= "identity" then
- sourcein = socket.source("http-chunked", thread)
- elseif message.env.CONTENT_LENGTH then
- sourcein = socket.source("by-length", thread,
- tonumber(message.env.CONTENT_LENGTH))
- else
- self:error( thread, 411, luci.http.protocol.statusmsg[411] )
- break;
- end
-
- -- FIXME: Close for POST requests
- close = true
- else
- self:error( thread, 405, luci.http.protocol.statusmsg[405] )
- break;
-
- end
-
-
- local host = self.vhosts[message.env.HTTP_HOST] or self.host
- if not host then
- self:error( thread, 500, "Unable to find matching host" )
- break;
- end
-
- local response, sourceout = host:process(
- message, sourcein, sinkerr,
- client, io.stderr
- )
- if not response then
- self:error( thread, 500, "Error processing handler" )
- end
-
- -- Post process response
- local sinkmode = close and "close-when-done" or "keep-open"
-
- if sourceout then
- if not response.headers["Content-Length"] then
- if message.http_version == 1.1 then
- response.headers["Transfer-Encoding"] = "chunked"
- sinkmode = "http-chunked"
- else
- close = true
- sinkmode = "close-when-done"
- end
- end
- end
-
- if close then
- response.headers["Connection"] = "close"
- end
-
-
- local sinkout = socket.sink(sinkmode, thread)
-
- local header =
- message.env.SERVER_PROTOCOL .. " " ..
- tostring(response.status) .. " " ..
- luci.http.protocol.statusmsg[response.status] .. "\r\n"
-
- header = header .. "Server: LuCI HTTPd/" .. tostring(VERSION) .. "\r\n"
-
-
- for k,v in pairs(response.headers) do
- header = header .. k .. ": " .. v .. "\r\n"
- end
-
- thread:send(header .. "\r\n")
-
- if sourceout then
- local eof = false
- repeat
- coroutine.yield()
- eof = not ltn12.pump.step(sourceout, sinkout)
- until eof
- end
- until close
-
- client:close()
-end