* General code cleanup
[project/luci.git] / core / src / ffluci / dispatcher.lua
index b60a9be..813e35d 100644 (file)
@@ -87,7 +87,6 @@ require("ffluci.template")
 require("ffluci.config")
 require("ffluci.sys")
 
-
 -- Sets privilege for given category
 function assign_privileges(category)
        local cp = ffluci.config.category_privileges
@@ -98,6 +97,18 @@ function assign_privileges(category)
        end
 end
 
+
+-- Builds a URL from a triple of category, module and action
+function build_url(category, module, action)
+       category = category or "public"
+       module   = module   or "index"
+       action   = action   or "index"
+       
+       local pattern = ffluci.http.get_script_name() .. "/%s/%s/%s"
+       return pattern:format(category, module, action)
+end
+
+
 -- Dispatches the "request"
 function dispatch(req)
        request = req
@@ -115,10 +126,11 @@ end
 
 -- Sends a 404 error code and renders the "error404" template if available
 function error404(message)
+       ffluci.http.set_status(404, "Not Found")
        message = message or "Not Found"
        
        if not pcall(ffluci.template.render, "error404") then
-               ffluci.http.textheader()
+               ffluci.http.set_content_type("text/plain")
                print(message)
        end
        return false    
@@ -126,10 +138,10 @@ end
 
 -- Sends a 500 error code and renders the "error500" template if available
 function error500(message)
-       ffluci.http.status(500, "Internal Server Error")
+       ffluci.http.set_status(500, "Internal Server Error")
        
        if not pcall(ffluci.template.render, "error500", {message=message}) then
-               ffluci.http.textheader()
+               ffluci.http.set_content_type("text/plain")
                print(message)
        end
        return false    
@@ -138,7 +150,7 @@ end
 
 -- Dispatches a request depending on the PATH_INFO variable
 function httpdispatch()
-       local pathinfo = os.getenv("PATH_INFO") or ""
+       local pathinfo = ffluci.http.get_path_info() or ""
        local parts = pathinfo:gmatch("/[%w-]+")
        
        local sanitize = function(s, default)
@@ -159,99 +171,130 @@ end
 
 -- The Action Dispatcher searches the module for any function called
 -- action_"request.action" and calls it
-function action(request)
-       local i18n = require("ffluci.i18n")
+function action(...)
+       local disp = require("ffluci.dispatcher")
+       if not disp._action(...) then
+               disp.error404()
+       end     
+end
+
+-- The CBI dispatcher directly parses and renders the CBI map which is
+-- placed in ffluci/modles/cbi/"request.module"/"request.action" 
+function cbi(...)
+       local disp = require("ffluci.dispatcher")
+       if not disp._cbi(...) then
+               disp.error404()
+       end
+end
+
+-- The dynamic dispatcher chains the action, submodule, simpleview and CBI dispatcher
+-- in this particular order. It is the default dispatcher.
+function dynamic(...)
+       local disp = require("ffluci.dispatcher")
+       if  not disp._action(...)
+       and not disp._submodule(...)
+       and not disp._simpleview(...)
+       and not disp._cbi(...) then
+               disp.error404()
+       end
+end
+
+-- The Simple View Dispatcher directly renders the template
+-- which is placed in ffluci/views/"request.module"/"request.action" 
+function simpleview(...)
+       local disp = require("ffluci.dispatcher")
+       if not disp._simpleview(...) then
+               disp.error404()
+       end
+end
+
+
+-- The submodule dispatcher tries to load a submodule of the controller
+-- and calls its "action"-function
+function submodule(...)
        local disp = require("ffluci.dispatcher")
+       if not disp._submodule(...) then
+               disp.error404()
+       end
+end
+
+
+-- Internal Dispatcher Functions --
+
+function _action(request)
+       local action = getfenv(2)["action_" .. request.action:gsub("-", "_")]
+       local i18n = require("ffluci.i18n")
        
-       i18n.loadc(request.module)
-       local action = getfenv()["action_" .. request.action:gsub("-", "_")]
        if action then
+               i18n.loadc(request.category .. "_" .. request.module)
+               i18n.loadc(request.category .. "_" .. request.module .. "_" .. request.action)
                action()
+               return true
        else
-               disp.error404()
+               return false
        end
 end
 
--- The CBI dispatcher directly parses and renders the CBI map which is
--- placed in ffluci/modles/cbi/"request.module"/"request.action" 
-function cbi(request)
-       local i18n = require("ffluci.i18n")
+
+function _cbi(request)
        local disp = require("ffluci.dispatcher")
        local tmpl = require("ffluci.template")
        local cbi  = require("ffluci.cbi")
+       local i18n = require("ffluci.i18n")
        
        local path = request.category.."_"..request.module.."/"..request.action
        
-       i18n.loadc(request.module)
-       
        local stat, map = pcall(cbi.load, path)
        if stat and map then
                local stat, err = pcall(map.parse, map)
                if not stat then
                        disp.error500(err)
-                       return
+                       return true
                end
+               i18n.loadc(request.category .. "_" .. request.module)
+               i18n.loadc(request.category .. "_" .. request.module .. "_" .. request.action)
                tmpl.render("cbi/header")
                map:render()
                tmpl.render("cbi/footer")
+               return true
        elseif not stat then
                disp.error500(map)
+               return true
        else
-               disp.error404()
+               return false
        end
 end
 
--- The dynamic dispatchers combines the action, simpleview and cbi dispatchers
--- in one dispatcher. It tries to lookup the request in this order.
-function dynamic(request)
+
+function _simpleview(request)
        local i18n = require("ffluci.i18n")
-       local disp = require("ffluci.dispatcher")
        local tmpl = require("ffluci.template")
-       local cbi  = require("ffluci.cbi")      
-       
-       i18n.loadc(request.module)
-       
-       local action = getfenv()["action_" .. request.action:gsub("-", "_")]
-       if action then
-               action()
-               return
-       end
        
        local path = request.category.."_"..request.module.."/"..request.action
-       if pcall(tmpl.render, path) then
-               return
-       end
        
-       local stat, map = pcall(cbi.load, path)
-       if stat and map then
-               local stat, err = pcall(map.parse, map)
-               if not stat then
-                       disp.error500(err)
-                       return
-               end             
-               tmpl.render("cbi/header")
-               map:render()
-               tmpl.render("cbi/footer")
-               return
-       elseif not stat then
-               disp.error500(map)
-               return
-       end     
-       
-       disp.error404()
+       local stat, t = pcall(tmpl.Template, path)
+       if stat then
+               i18n.loadc(request.category .. "_" .. request.module)
+               i18n.loadc(request.category .. "_" .. request.module .. "_" .. request.action)
+               t:render()
+               return true
+       else
+               return false
+       end
 end
 
--- The Simple View Dispatcher directly renders the template
--- which is placed in ffluci/views/"request.module"/"request.action" 
-function simpleview(request)
+
+function _submodule(request)
        local i18n = require("ffluci.i18n")
-       local tmpl = require("ffluci.template")
-       local disp = require("ffluci.dispatcher")
-       
-       local path = request.category.."_"..request.module.."/"..request.action
+       local m = "ffluci.controller." .. request.category .. "." ..
+        request.module .. "." .. request.action
+       local stat, module = pcall(require, m)
        
-       i18n.loadc(request.module)
-       if not pcall(tmpl.render, path) then
-               disp.error404()
+       if stat and module.action then 
+               i18n.loadc(request.category .. "_" .. request.module)
+               i18n.loadc(request.category .. "_" .. request.module .. "_" .. request.action)
+               return pcall(module.action)
        end
+       
+       return false
 end
\ No newline at end of file