Some questions about the Luci <一>

Source: Internet
Author: User
Tags local time lua require unpack

Recently, due to the project's reasons, now summarizes several points:

The process of 1.LUCI operation.

For:

First, we start with the/www/cgi-bin/file and run the code in the Luci file:

#!/usr/bin/lua
luci.dispatcher.indexcache = "Tmp.luci-indexcache"
Luci.sgi.cgi.run ()

Then into the sgi/Cgi.lua file, a function is Limitsource (handle, limit), mainly the number of the limit of the character from the stdin inside.

Another function is that the page generation after run () will always be done in this function.

Run ()
   Local x = coroutine.create (luci.dispatcher.httpdispatcher) while
   coroutine.status (x)  ~= ' dead ' do
   //Run the Httpdispatcher created above, that is, run the parameter for the above local R
   Local Res. ID, data1, data2 = Coroutine.resume (x, R)
   if active then
      if Id = = 1 Then     --http.response-line
  
   if id = = 2 then     --Prepare header
      If id = = 3 then     --Write header, blank, default to stdout
      If id = = 4 then     --write BODY
   if id = = 5 then     --eof
      If id = = 6 then     
    end
end End
  

Then, enter httpdispatcher (request, prefix)//parameters are placed in the context

<pre name= "code" class= "HTML" >
<pre name= "code" class= "html" >local pathinfo = Http.urldecode (request:getenv ("Path_info") or "", true)
  for _, Node in ipairs (prefix) does
r[#r +1] = node    -assigns node to r{}
  End

  Local Stat, err = Util.coxpcall (function ()
Dispatch (context.request)
  End, error500)
Next, enter the dispatch (Request) function,
A. Setting language B. Creating A node-tree node tree structure local c = Ctx.tree local stat If not C then C = Createtree ()//This function creates a nod from the index function under the controller E-tree structure file End b. Createtree () function If not index then CreateIndex ()//This function defines path, Suff, determines the condition and then enters different branches,//create  Index_fastindex (Path, Suff), Createindex_plain (Path, Suff) End Local track = {}--each layer places the found node information in the () for I, S-in

Ipairs (Request) do Util.update (track, c)--update (T, updates) t the table to be updated, and the updates contain the worthy tables that need to be updated.  C. The part that needs to be displayed if (c and C.index) or not track.template the then initialization template defines tpl.context.viewns = Setmetatable () D. Certified If Track.sysauth Then Local Sauth = require "Luci.sauth"//assigns GetCookie and Sysauth attributes to Sess If not sess then Sess = Luci.http.getcookie ("Sysaut  H ") Sess = Sess and Sess:match (" ^[a-f0-9]*$ ") Verifytoken = True End//Read session value returns its content Local Sdat = Sauth.read (sess) If Sdat then Else local EU = http.getenv ("Http_auth_user") Local EP = Http.getenv ("Http_auth_p ") End F. Show/Process C is the return value of Createtree () tree, according to the differenttypes are handled differently. If C then if Type (c.target) = = ' function ' then target = c.target Elseif type (c.target) = = ' table ' then target = C.target. Target End End
2. Questions about root and mini login.

For:

Root=node () Calls Dispatcher.lua in node (...) function, node (...) Call the _create_node (path) function, which defines the outermost node, which is the topmost menu display.

If not Root.target then
root.target = Alias ("admin")     //Call Dispatcher.lua in Alias (...) function, redirect to another node, in function to continue the admin node to req, then dispatch (req)
Root.index = True
End
Local page = node ("admin")    / /Will admin. Write to Context.treecache[name]
page.target = firstchild ()     //Call FirstChild () function in Dispatcher.lua, return { Type = "FirstChild", target = _firstchild}, and then calls _firstchild () to execute the lowest order of node to the dispatch () function.
Page.title = _ ("Administration")  //title
Page.order = Ten      //order
Page.sysauth = "root"  // Authenticated User Login
Page.sysauth_authenticator = "Htmlauth"   //Call Dispatcher.lua in the Htmlauth () function to detect the legality of login.
Page.ucidata = True   
Page.index = True

Method: A copy of the Admin folder to Mini, the Mini in the Index.lua will page.sysauth = "root" and Page.sysauth_authenticator = "Htmlauth" commented out, Then click on the User button on the pop-up page and it will go directly to the system. 3. For the analysis of the entry () function.

For:

3.1 Entry (path, target, title, order) for example:

Entry ({"admin", "system"}, alias ("admin", "System", "system"), _ ("System"), "("). "Index = True

Path: Virtual path

Target: Destination function call

Title: The caption displayed on the page

Order: The sequence of node under the same level. (optional)

Local c = node (path)//unpack returns all values in path and passes to node for parameters, and then calls node two to create the node unpack

Pass the parameters in separately

C.target = target//After the value is passed in, alias (..) when the Node-tree is first constructed. The function will be in entry (...). function, and then call Dispatch (req) in the alias () function.

C.title = Title

C.order = Order

C.module = getfenv (2). __name

3.2. Entry ({"admin", "System", "system"}, CBI ("Admin_system/system"), _ ("System"), 1)

First, the CBI () function executes first, return {type = "CBI", config = config, model = model, target = _CBI} This sentence, at the beginning, the _CBI function will not be executed, only in the dispatch () function Before it can be executed.

The CBI function returns a value of four, Type,config,model,target

When clicking on the CBI-related request, there is an if judgment in the Display/Processing section of the dispatch () function,

If C then
		if Type (c.target) = = "function" then   //when C.target type is function
			, target = C.target
		Elseif type ( C.target) = = "Table" then  //When the C.target type is table,
			target = c.target.target//is        the table attribute target = "_CBI" The target is given a follow-up process.
		End
	End

In _CBI (self, ...) function,

Local CBI = require "LUCI.CBI"
local TPL = require "luci.template"
local http = require "luci.http"

local conf IG = Self.config or {}     //The second parameter returned by CBI () to config
Local maps = Cbi.load (Self.model, ...)  Give the third argument to load (), and then to maps
in the Cbi.lua file, the model is actually the path, the load path

Next is a for loop, where each node first needs a map to draw the frame, and then a layer of the drawing Control.

For I, res in ipairs (maps)  do
	res.flow = config    //map.flow
	Local cstate = Res:parse ()    // Call Map.parse (self, readinput,...)
Call Node.parse (self, ...), (UCI is primarily a platform for data interaction with Luci. )
Function map.parse (self, readinput, ...)
	Formvalue ("Cbi.skip") 
	node.parse (self, ...)
	If Self.save then     //If the Save button of the map is clicked, or the other button is clicked, the function inside the UCI will be triggered to handle the related operation.
                              For example: On_save, On_before_save,on_after_save, On_before_commit, on_after_commit,on_before_apply, etc.
	If Self:submitstate () then  //If the map's Submit button is clicked
End

map = Class (node)   //map is a subclass of node, Then Map.parse will execute the Node.parse () method, function Node.parse (self, ...)
		For-K, child in Ipairs (Self.children) do
			child:parse ()
		End

End before this function executes, call node.__init__ (self, title, description), Self.children = {}

Local class= Util.class Class () function return setmetatable ({}, {__call = _instantiate,__index = base)} When called, Call _instantiate ( Class, ...), called inst:__init__ (...) in the function The function initializes the specific class, returning the class.

Map = Class (Node)
function map.__init__ () function
map.fromvalue (self, key)
function map.formvaluetable ( Self, key)
function map.get_scheme ()
function map.submitstate (self)
functoin map.chain ()
function Map.state_handler () function
map.parse () function
Map.render () function
map.section (self, class,...)
function Map.add (self, sectiontype)
function map.set (self, section,...)
function Map.del ()
function Map.get ()
<pre name= "code" class= "HTML" >
3.3 M:chain ("Luci")   //inserting external config information into map
S = M:section (Typedsection, "", "")//map:section creates a child section, where if it is an instance of abstraction, call Node:append () Table.insert ( Self.children, obj) statement.
S is an instance of the class typedsection generation.  S.addremove = false//when the Typedsection () function is executed, this and the following options are judged s.anonymous = True S.tab = S:tab ("General", translate ("General Settings "))//Define a tab to S, call the Abstractsection:tab (TAB,TITLE,DESC) function, where self.tab_names[#self. tab_names+1] = tab self.tab
S[tab] = {title = title, Description = desc, childs = {}} would tab to the tabs array for each of the tab_names,tab parameters. o = s:taboption ("General", Dummyvalue, "_systime", Translate ("Local Time"))//Call Abstractsection:taboptoin (),
		Then call abstractsection.option (Self, ...), if instanceof (class, Abstractvalue) then//If Dummyvalue is an instance of Abstractsection   Local obj = Class (Self.map, self, option, ...) 
		Instantiate Dummyvalue class Self:append (obj)//return obj appended to abstractsection self.fields[option] = obj//Assign object to Fields[option] return obj//returns obj End o.template = "Admin_system/clock_status"//dummyvaluE object After instance O call template function dummyvalue.__init__ (self, ...)
	Abstractvalue.__init__ (self, ...)  Self.template = "Cbi/dvalue"//This sentence o.template call template/cbi/dvalue.htm file Self.value = Nil End o = s:taboption ("General", Value, "hostname", translate ("hostname")) The instance of the//value class is given an o O.datatype = "hostname"//O connected to the CBI folder, Datatype.lua file funct Ion O.write (Self, section, value) Value.write (Self, section, value)//Call Abstractvalue.write () method, call Uci:set () to write to config file Luci.sys.hostname (value)//Gets or changes the current hostname End
3.4 Entry ({"admin", "services"}, FirstChild (), _ ("services"), +). Index = True

Call FirstChild () in Dispatcher.lua,
function firstchild ()
   return {type = "FirstChild", target = _firstchild}   When the post-Display section executes dispatch (), call the _firstchild () function,
if node and Node.nodes and Next (node.nodes) then
	  Local K, V for
	  K, V in pairs (node.nodes) does
		 if not lowest or
			(V.order or) < (Node.nodes[lowest].order or)
		 Then
  lowest = k
		 end End end
   path[#path +1] = lowest--Appends the extra node to path
   Dispatch (PATH)-    - The most critical line of code, called Dispatch (path), PATH has changed
3.5 entry ({"admin", "logout"}, Call ("Action_logout"), _ ("logout"), 90)

Call () in Dispatcher.lua, function calls
(name, ...)
	return {type = "call", argv = {...}, name = name, target = _call}  //When the post-Display section executes dispatch (), the _call () function is called,
local funct Ion _call (Self, ...)
	Local func = Getfenv () [Self.name]     //Gets the folder path where the current function
	is located if #self. argv > 0 Then
		return func (Unpack (SELF.ARGV), ...)   
	else
		return func (...)    Call the corresponding function at the same path as the current function
	end
End

3.6 Entry ({"admin", "System", "Startup"},form ("Admin_system/startup"), _ ("Startup"), 45)

function form (model)
	Return {type = "CBI", model = model, target = _form}
End
when executing the dispatch () function, execute the _form () function, C3/>local maps = Luci.cbi.load (Self.model, ...)
For I, res in ipairs (maps) does 
	Local cstate = Res:parse ()   
	If cstate and (not state or cstate < State) then  
		S Tate = cstate
	end
End
Http.header ("X-cbi-state", State or 0)   //context.headers[key:lower ()] = value     
								  //coroutine.yield (2, key, value) 
Tpl.render ("header")      //render (name, scope) return template (name): render (Scope or    			               //getenv (2)) Then call template (name): Reader () draw header.htm
for I, res in ipairs (maps) do
	res:render ()          
End
Tpl.render ("footer")  //Draw footer.htm

3<span style= "font-family: the song Body;" >.7 entry ({"admin", "Network", "Wireless"}, Arcombine ("Admin_network/wifi_overview"), CBI ("Admin_ Network/wifi ")), _ (" WiFi "), </span>
Arcombine (template, CBI) call Dispatcher.lua file in function arcombine (TRG1, trg2)
	Return {type = "Arcombine", env = getfenv (), target = _arcombine, targets = {trg1, trg2}}

Function _arcombine (self, ...)
	Local argv = {...}
	Local target = #argv > 0 and self.targets[2] or self.targets[1]   
	setfenv (target.target,self.env)
	target: Target (unpack (argv))   //One after the other to execute the corresponding function,
End
3.8 entry ({"admin", "status", "Overview"}, Template ("Admin_status/index"), _ ("Overview"), 1)

Template () calls the template (name) function in the Dispatcher.lua file,
Return {type = "template", view = name, target = _template}
When executing the dispatch () function, execute _template = function (self, ...) require "luci.template". Render (Self.view), Draw admin_status/ Index.htm

4.formvalue how to deal with the value.

Answer: Dispatcher.lua in the Authenticator.htmlauth () function,

Local user = Luci.http.formvalue ("username")    
local pass = Luci.http.formvalue ("password")

Call the Formvalue () function from the Http.lua file to get the value

Call function Formvalue (name, Noparse)

Return context.request:formvalue (name, Noparse)

End

Then call Request.formvalue (self, name, noparse)

If name then return Self.message.params[name]

Then return to Message.params[name in request]

-Http-message Table
self.message = {
	env = env,
	Headers = {},
	Params = Protocol.urldecode_params (env. Query_string or ""),
}

Upload the original "Username" to the params, and then call the Http/protocol.lua file

Function urldecode_params (URL, tbl)
Local params = TBL or {}
If url.find ("?") then
URL = url:gsub ("^.+%?" ( [^?] +) ","%1 ")  //^ the beginning of the match, + matches 1 or more times,%. Escapes the question mark, and the third parameter represents capturing the first matching string. ^? Represents a part of a non-question mark,. + is the longest match.
End
<span style= "color: #3366ff;" >//by Wireshark analysis, Post/cgi-bin/luci http/1.1 (application/x-www-form-urlencoded)
URL:HTTP://192.168.1.1/ Cgi-bin/luci?username=root&password=admin
content-length:28
				form iten: "username" = "root"
					Key: Username
					value:root
				Form item: "Password" = "admin"
					Key:password
					value:admin
Visible: Still processing into key-value pair. </span>
For-pair in Url:gmatch ("[^&;] + ") do
		--find key, value
		local key = UrlDecode (Pair:match (" ^ ([^=]+) "))
		local val = UrlDecode (Pair:match (" ^[^= ]+= (. +) $ "))
//Call UrlDecode in Pair.match () Find key, Val
		--store value
		If type (key) = =" string "and Key:len () > 0 then< C6/>//key is the first word passed in the ID (username), and then Val assigns to Params[name]
			If type (val) ~= "string" Then val = "" "End
			If not Params[key ] then    //Login page pass in the value entered here
				Params[key] = val      
			Elseif type (Params[key] ~= "table" then
				params[key] = { Params[key], val}
			Else
				table.insert (params[key],val)  
			end
	End
Return params
End

At this point, the desired value in the URL is obtained. Then proceed with the subsequent processing.

5. What happens when you click the login button.

Answer: In Sysauth.htm,

<formmthod= "POST" action= "<%=pcdata (luci.http.getenv (" Request_uri "))%>" >

When the button is clicked, it jumps to the URL specified by the action. In the Dispatcher.lua file Dispatch () function,

Tpl.context.views setmetable ({

.....},{__index=function (Table,key)
		If key = = "Controller" then	return Build_url ()  
		Elseif key = = " Request_uri "	then return Build_url (Unpack (Ctx.requestpath))
})
when clicked Login, the page will jump to/, then/admin, if authentication is required, Then the next will pop up the Htmlauth.htm page, and then if there is no verification success, then continue this page, if successful, then continue to jump/, then admin/, when the post came to the message, and then alias to entry.order the smallest node, it is clearly/ Admin/status.lua, then status this node will alias to overview this node. The most important is the authentication section of dispatch () in the Diapatcher.lua file. The
logic of Apply,apply&save,reset is the same as this one.

When click Login, the page will jump to/, then/admin, if the need for certification, then the next pop-up htmlauth.htm page, and then if there is no verification success, then continue this page, if successful, then continue to jump/, and then admin/, then post to the information, Then alias to entry.order the smallest node, apparently/admin/status.lua, and then status this node will alias to overview node. The most important is the authentication section of dispatch () in the Diapatcher.lua file.

The logic of Apply,apply&save,reset is the same as this one.



















Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.