1. 多語言css
1)檢查:html
opkg list | grep luci-i18n-
2)安裝語言包:node
opkg install luci-i18n-hungarian
2.uhttpd
這個是LuCI所在的Web Server。docroot在/www下邊,index-html指向了/cgi-bin/luci,注意這是相對於docroot而言的路徑。
openwrt中利用它做爲web服務器,實現客戶端web頁面配置功能。對於request處理方式,採用的是cgi,而所用的cgi程序就是luci。 linux
1)工做框架以下圖所示: web
Client端和serv端採用cgi方式交互,uhttpd服務器的cgi方式中,fork出一個子進程,子進程利用execl替換爲luci進程空間,並經過setenv環境變量的方式,傳遞一些固定格式的數據(如PATH_INFO)給luci。另一些非固定格式的數據(post-data)則由父進程經過一個w_pipe寫給luci的stdin,而luci的返回數據則寫在stdout上,由父進程經過一個r_pipe讀取。 緩存
2)luci 文件(權限通常是 755 ) , luci 的代碼以下: 服務器
#!/usr/bin/lua -- 執行命令的路徑 cookie
require"luci.cacheloader" -- 導入 cacheloader 包 session
require"luci.sgi.cgi" -- 導入 sgi.cgi 包 架構
luci.dispatcher.indexcache = "/tmp/luci-indexcache" --cache 緩存路徑地址
luci.sgi.cgi.run() -- 執 行 run 方法,此方法位於 /usr/lib/lua/luci/sgi/cgi.lua中
3)web配置時的數據交互:
首次運行時,是以普通的file方式得到docroot/index.html,該文件中以meta的方式自動跳轉到cgi的url,這是web服務器的通常作法。
而後第一次執行luci,path_info='/',會alise到'/admin'('/'會索引到 tree.rootnode,並執行其target方法,即alise('/admin'),即從新去索引adminnode,這在後面會詳細描述),該節點須要認證,因此返回一個登陸界面。
第3次交互,過程同上一次的,只是這時已post來了登陸信息,因此serv端會生成一個session值,而後執行'/admin'的target(它的target爲firstchild,即索引第一個子節點),最終返回/admin/status.html,同時會把session值以cookie的形式發給client。這就是從原始狀態到獲得顯示頁面的過程,以後主要就是點擊頁面上的鏈接,產生新的request。
每一個連接的url中都會帶有一個stok值(它是serv生成的,並放在html中的url裏),而且每一個新request都要帶有session值,它和stok值一塊兒供serv端聯合認證。
初始階段http報文,能夠看到從第2次交互開始,全部request都是cgi方式(除一些css、js等resource文件外),且執行的cgi程序都是luci,只是帶的參數不一樣,且即便所帶參數相同(如都是'/'),因爲須要認證,執行的過程也是不一樣的。
正是因爲多種狀況的存在,使得luci中須要多個判斷分支,代碼多少看起來有點亂,但openwrt仍是把這些分支都糅合在了一個流程線中。下面首先給出總體流程,首先介紹一下lua語言中一個執行方式coroutine,它能夠創造出另外一個執行體,但卻沒有並行性,以下圖所示,每一時刻只有一個執行體在執行,經過resume、yield來傳遞數據,且數據能夠是任意類型,任意多個的。
Luci正是利用了這種方式,它首先執行的是running()函數,其中create出另外一個執行體httpdispatch,每次httpdispatch執行yield返回一些數據時,running()函數就讀取這些數據,作相應處理,而後再次執行resume(httpdispath),……如此直到httpdispatch執行完畢,以下圖所示:
如上圖所示,其實luci真正的主體部分正是dispatch,該函數中有多個判斷分支,所有糅合在一塊兒。
在controller目錄下,每一個.lua文件中,都有一個index()函數,其中主要調用entry()函數,形如entry(path,target,title,order),path形如{admin,network,wireless},entry()函數根據這些建立一個node,並把它放在全局node-tree的相應位置,後面的參數都是該node的屬性,還能夠有其餘的參數。其中最重要的就是target。
Createtree()函數就是要找到controller目錄下全部的.lua文件,並找到其中的index()函數執行,從而生成一個node-tree。這樣作的io操做太多,爲了效率,第一次執行後,把生成的node-tree放在/tmp/treecache文件中,之後只要沒有更新(通常狀況下,服務器裏的.lua文件是不會變的),直接讀該文件便可。生成的node-tree以下:
這裏要注意的是,每次dispatch()會根據path_info逐層索引,且每一層都把找到的節點信息放在一個變量track中,這樣作使得上層node的信息會影響下層node,而下層node的信息又會覆蓋上層node。好比{/admin/system},最後的auto=false,target=aa,而因爲admin有sysauth值,它會遺傳給它的子節點,也即全部admin下的節點都須要認證。
對每一個節點,最重要的屬性固然是target,這也是dispatch()流程最後要執行的方法。target主要有:alise、firstchild、call、cbi、form、template。這幾個整體上能夠分紅兩類,前兩種主要用於連接其它node,後一個則是主要的操做、以及頁面生成。下面分別描述。
連接方法:在介紹初始登陸流程時,已經講到了這種方法。好比初始登陸時,url中的path_info僅爲'/',這應該會索引到rootnode節點。而該節點自己是沒有內容顯示的,因此它用alias('admin')方法,自動連接到admin節點。再好比,admin節點自己也沒有內容顯示,它用firstchild()方法,自動連接到它的第一個子節點/admin/status。
操做方法:這種方法通常用於一個路徑的葉節點leaf,它們會去執行相應的操做,如修改interface參數等,而且動態生成頁面html文件,傳遞給client。這裏其實是利用了所謂的MVC架構,這在後面再描述,這裏主要描述luci怎麼把生成的html發送給client端。
Call、cbi、form、template這幾種方法,執行的原理各不相同,但最終都會生成完整的http-response報文(包括html文件),並調用luci.template.render(),luci.http.redirect()等函數,它們會調用幾個特殊的函數,把報文內容返回給luci.running()流程。
如上圖所示,再聯繫luci.running()流程,就很容易看出,生成的完整的http-response報文會經過io.write()寫在stdout上,而uhttpd架構已決定了,這些數據將傳遞給父進程,並經過tcp鏈接返回給client端。
因爲節點是由上而下逐層索引的,因此只要一個節點有sysauth值,那麼它全部的子節點都須要認證。不難想象,/admin節點有sysauth值,它如下的全部子節點都是須要認證才能查看、操做的;/mini節點沒有sysauth值,那麼它如下的全部子節點都不須要認證。
luci中關於登錄密碼,用到的幾個函數爲:
能夠看出它的密碼是用的linux的密碼,而openwrt的精簡內核沒有實現多用戶機制,只有一個root用戶,且開機時自動以root用戶登陸。要實現多用戶,必須在web層面上,實現另一套(user、passwd)系統。
另外,認證後,serv端會發給client一個session值,且它要一直以cookie的形式存在於request報文中,供serv端來識別用戶。這是web服務器的通常作法,這裏就很少講了。
這實際上是luci的精華所在,/usr/lib/lua/luci/下有三個目錄model、view、controller,它們對應M、V、C。下面簡單介紹生成界面的方法。
Call()方法會調用controller裏的函數,主要經過openwrt系統的uci、network、inconfig等工具對系統進行設置,若是須要還會生成新界面。動態生成界面的方法有兩種,一是經過cbi()/form()方法,它們利用model中定義的模板map,生成html文件;另外一種是經過template()方法,利用view中定義的htm(一種相似html的文件),直接生成界面。
上面的標題是由node-tree生成的,下面的內容由每一個node經過上面的方法來動態生成。這套系統是很複雜的,但只要定義好了,使用起來就很是方便,增長頁面,修改頁面某個內容等操做都很是簡單。
8)啓動:
/etc/init.d/uhttpd start
9)開機自啓動:
/etc/init.d/uhttpd enable
5.參考文獻
http://www.cnblogs.com/zmkeil/archive/2013/05/14/3078774.html