天天看點

關于luci的幾個問題<二>

1.Luci/sgi/cgi.lua和http.lua和dispatcher.lua關系?

答:

關于luci的幾個問題<二>

對每一個node,最重要的屬性是target,也是dispatch()流程最後要執行的方法。各個方法alise、firstchild、call、cbi、form、template。前兩種主要連結其他node,後一個則是主要的操作、以及頁面生成。後四種方法最終生成完整的http-response封包(包括HTML檔案)。

生成的http-response封包會通過io.write()寫在stdout上,然後發送給client。

http.lua

Context = util.threadlocal()
Request = util.class()
Function Request.__init__(self, env, sourcein, sinkerr)
Function Request.formvalue(self, name, noparse)
Function Request.formvaluetable(self, prefix)
Function Request.content(self)
Function Request.getcookie(self, name)
Function Request.getenv(self, name)
Function Request.setfilehandler(self,  callback)
Function Request._parse_input(self)
Function close()   //執行httpdispatch(request, prefix)中luci.http.close()時,
If not context.eoh then
Context.eoh = true
Coroutine.yield(3)
End
If not context.closed then
Context.closed = true
Coroutine.yield(5)
End
End
Function content()
Function formvalue()
Function formvaluetable(prefix)
Function getcookie(name)
Function getenv(name)
Function setfilehandler(callback)
Function header(key, value) //1.執行dispatch()函數luci.http.header(“SetCookie”,”sysauth=” .. Sid .. “;path=”.                             //.build_url())時調用此函數;
                                                  //2.調用_cbi()函數中http.header(“X-CBI-State”, state or 0)時;
If not context.headers  then
Context.headers = {}
End
Context.headers[key:lower()] = value
Coroutine.yield(2, key, value)
End
 
Function prepare_content(mime)
Function source()
Function status(code, message)   //1.dispatcher.lua中執行error404(message)函數,然後執行此函數;                                                      //2.error500(message)函數;
                                   // 3.還有dispatch()中luci.http.status(403,”Forbidden”);
Code = code or 200
Message = message or “OK”
Context.status = code
Coroutine.yield(1, code, message)
end
Function write(content, src_err)  //1.在error404()中執行luci.http.write(message)時,
           
//2.在error500(message)中luci.http.write(message)時,
If not content then
If src_err then
Error(src_err)
Else 
Close()
End
Return true
Elseif #content == 0 then
Return true
Else
....
Context.eoh = true
Coroutine.yield(3)
End
Coroutine.yield(4, content)
Return true
End
 
Function splice(fd, size)       //httpclient檔案夾下的receive.lua包含nixio.splice()
Coroutine.yield(6, fd, size)
end
Function redirect(url)
Function build_querystring(q)
Urldecode = protocol.urldecode
Urldecode = protocol.urlencode
Function write_json(x)
 
Cgi.lua
Function run()
If active then
If id == 1   io.write(“status:” .. Tostring(data1).. “ “ .. Data2 .. “\r\n”)
If id == 2   hcache = hcache .. Data1 .. “:” .. “data2 .. “\r\n”
If id == 3   io.write(hcache)          io.write(“\r\n”)
If id == 4   io.write(tostring(data1 or “”))
If id == 5   io.flush()                io.close()              active = false
If id == 6   data1:copyz(nixio.stdout, data2)  data1:close()
End
End
           

2.Web頁面和 config檔案中的資料如何互動?

答:當點選system下system标簽,local Time選項、Hostname選項、Timezone選項,這三個開始的時候就有值,解析如下:

O = s:taboption(“general”, Value, “hostname”, translate(“Hostname”))
O.datatype = “hostname”
 
Function o.write(self, section, value)
Value.write(self, section, value)    //調用cbi.lua中Value類,因為Value繼承自AbstractValue類,然後調用AbstractValue.write(self, section, value)方法,return self.map:set(section,self.option, value),然後調用Map.set(self, section, option, value),裡面語句如下:
If type(value) ~= “table” or #value > 0 then
If option then	return self.uci:set(self.config, section, option,value)  //然後uci.cursor:set()就把資料設定到config檔案裡面了。
Else return self.uci:set(self.config,section, value)
Else return Map.del(self, section, option)
End
 
Luci.sys.hostname(value)   //調用sys.lua檔案中hostname(newname)目的是得到或設定目前hostname 
End
           

在view/header.htm中,

<%+header%>
<form mthod=”post” name=”cbi” action=”<%=REQUEST_URI%>” enctype=”multipart/form-data” οnreset=”return cbi_validate_reset(this)” οnsubmit=”return cbi_validate_form(this,’<%:Some fields are invalid, cannot save values!%>’)”>
           

在view/footer.htm中有apply&save、apply、reset三個按鈕,其中apply&save按鈕這樣寫:

<%if not autoapply and not flow.hideapplybtn then %>
<input class = “cbi-button cbi-button-apply” type = “submit” name =”cbi.apply” value = “<%:Save & Apply%>” />
<% end %>
</FORM>
           

當點選Save&Apply按鈕的時候,type=”submit”,然後執行action動作,跳轉到REQUEST_URI表示的頁面。執行onsubmit動作,

在cbi.lua檔案中,

Template.parse(self, readinput)

Return Map.formvalue(self, “cbi.submit”) and FORM_DONE or FORM_NODATA

然後調用Map.formvalue(self, key) return self.readinput and luci.http.formvalue(key)

調用http.lua中formvalue()可以得到界面裡面的資料。