Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
篇文章給大家講解 dhtmlxGantt可以加載或支持哪些數(shù)據(jù)格式。
點(diǎn)擊獲DhtmlxGantt官方正式版
JSON 數(shù)據(jù)可以在數(shù)據(jù)對象的“集合”屬性中包含任意數(shù)量的附加數(shù)組。代碼如下所示:
{
"tasks":[
{"id":"1", "text":"Project #2", "start_date":"01-04-2020", "duration":18,
"progress":0.4, "open": true},
{"id":"2", "text":"Task #1", "start_date":"02-04-2020", "duration":8,
"progress":0.6, "parent":"1"},
{"id":"3", "text":"Task #2", "start_date":"11-04-2020", "duration":8,
"progress":0.6, "parent":"1"}
],
"links":[
{"id":"1", "source":"1", "target":"2", "type":"1"},
{"id":"2", "source":"2", "target":"3", "type":"0"},
{"id":"3", "source":"3", "target":"4", "type":"0"},
{"id":"4", "source":"2", "target":"5", "type":"2"}
],
"collections": {
"sections":[
{"value":"1","label":"Simple"},
{"value":"2","label":"Complex"},
{"value":"3","label":"Unknown"}
]
}
}
代碼如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<projects>
<project id="1" name="project1" startdate="2006,12,14">
<task id="1">
<name>project1 task1</name>
<est>2006,12,14</est>
<duration>120</duration>
<percentcompleted>60</percentcompleted>
<predecessortasks></predecessortasks>
<childtasks>
<task id="2">
<name>project1 task2</name>
<est>2006,12,14</est>
<duration>100</duration>
<percentcompleted>20</percentcompleted>
<predecessortasks></predecessortasks>
<childtasks></childtasks>
</task>
<task id="6">
<name>project1 task6</name>
<est>2006,12,15</est>
<duration>90</duration>
<percentcompleted>10</percentcompleted>
<predecessortasks>2</predecessortasks>
<childtasks></childtasks>
</task>
</childtasks>
</task>
</project>
<project id="2" name="project2" startdate="2006,12,20">
<task id="12">
<name>project2 task12</name>
<est>2006,12,20</est>
<duration>140</duration>
<percentcompleted>60</percentcompleted>
<predecessortasks></predecessortasks>
<childtasks>
<task id="14">
<name>project2 task14</name>
<est>2006,12,20</est>
<duration>100</duration>
<percentcompleted>20</percentcompleted>
<predecessortasks></predecessortasks>
<childtasks></childtasks>
</task>
</childtasks>
</task>
</project>
</projects>
dhtmlxGantt是用于跨瀏覽器和跨平臺應(yīng)用程序的功能齊全的Gantt圖表,可滿足項(xiàng)目管理應(yīng)用程序的所有需求,是最完善的甘特圖圖表庫。了解更多DhtmlxGantt相關(guān)內(nèi)容和資訊,歡迎訪問慧都網(wǎng)獲取。
甘特圖控件交流群:764148812 歡迎進(jìn)群交流討論
篇文章給大家講解如何利用dhtmlxGantt從對象和服務(wù)器加載數(shù)據(jù)。
要從對象加載數(shù)據(jù),請使用parse方法:從內(nèi)聯(lián)數(shù)據(jù)源加載
var data = {
tasks:[
{id:1, text:"Project #1", start_date:"01-04-2020", duration:18},
{id:2, text:"Task #1", start_date:"02-04-2020", duration:8, parent:1},
{id:3, text:"Task #2", start_date:"11-04-2020", duration:8, parent:1}
]
};
gantt.init("gantt_here");
gantt.parse(data);
要從服務(wù)器加載數(shù)據(jù),請使用load方法:甘特圖.html
gantt.init("gantt_here");
gantt.load("data.json");
load方法將向指定的 url 發(fā)送一個 AJAX 請求,并期望以一種受支持的格式響應(yīng)數(shù)據(jù)。例如:數(shù)據(jù).json
{
"tasks":[
{"id":1, "text":"Project #1", "start_date":"01-04-2020", "duration":18},
{"id":2, "text":"Task #1", "start_date":"02-04-2020","duration":8, "parent":1},
{"id":3, "text":"Task #2", "start_date":"11-04-2020","duration":8, "parent":1}
],
"links":[
{"id":1, "source":1, "target":2, "type":"1"},
{"id":2, "source":2, "target":3, "type":"0"}
]
}
格式在方法的第二個參數(shù)中指定:“json”、“xml”或“oldxml”。
gantt.load("data.xml", "xml");
在服務(wù)器上,您可以擁有一個包含數(shù)據(jù)的靜態(tài)文件,也可以擁有一個從數(shù)據(jù)源收集數(shù)據(jù)并將其寫入響應(yīng)的腳本。服務(wù)器端實(shí)現(xiàn)取決于您要使用的框架。
例如,在 Node.js 的情況下,我們應(yīng)該為 URL 添加一個服務(wù)器路由,甘特圖將在其中發(fā)送 AJAX 數(shù)據(jù)請求。
gantt.load("/data");
它將生成 JSON 格式的相應(yīng)響應(yīng)。
app.get("/data", function(req, res){
db.query("SELECT * FROM gantt_tasks", function(err, rows){
if (err) console.log(err);
db.query("SELECT * FROM gantt_links", function(err, links){
if (err) console.log(err);
for (var i = 0; i < rows.length; i++){
rows[i].start_date = rows[i].start_date.format("YYYY-MM-DD");
rows[i].open = true;
}
res.send({ tasks:rows, links : links });
});
});
});
dhtmlxGantt是用于跨瀏覽器和跨平臺應(yīng)用程序的功能齊全的Gantt圖表,可滿足項(xiàng)目管理應(yīng)用程序的所有需求,是最完善的甘特圖圖表庫。了解更多DhtmlxGantt相關(guān)內(nèi)容,請鎖定本套系列教程。
甘特圖控件交流群:764148812 歡迎進(jìn)群交流討論
更多正版甘特圖軟件下載、購買、授權(quán)咨詢,請點(diǎn)這里!
×00 簡介
0×01 解碼過程總述
0×02 瀏覽器中的詞法分析
0×03 HTML編碼與HTML解析
0×04 常見誤區(qū)
0×05 瀏覽器有趣的容錯行為
0×06 結(jié)語
*原創(chuàng)作者:VillanCh
0×00 簡介
編碼問題一直是一個痛點(diǎn),在wooyun有一篇XSS編碼的文章,講到一些痛點(diǎn),既然準(zhǔn)備再次完成一篇對XSS中的編碼講解,同時也對得起這個文章的名字,本文就比較系統(tǒng)的講一下瀏覽器Lexer中HTML編碼處理的問題與XSS的html編碼原理剖析。
0×01 解碼過程總述
在開始XSS之前,我們?nèi)绻磺宄幋a解碼的過程,將會對XSS造成非常大的困難,不懂得編碼而亂插一氣,如果你是自動化工具還好但是如果你是手動XSS,那么你可就遭殃了,運(yùn)氣好做出來,運(yùn)氣不好就怎么樣也解決不了編碼問題了。
了解編碼過程首先從瀏覽器解析來講吧
對瀏覽器解析HTML有過了解的同學(xué),肯定是清楚瀏覽的的這些工具原理,一般來講瀏覽器通過Lexer-Parser來解析生成Dom樹然后再對CSS元素進(jìn)行渲染,最后執(zhí)行javascript(瀏覽器腳本),但是為什么要講這一部分呢?原因就是這和解碼的順序是有關(guān)系的!
舉一個簡單的例子吧:在HTML(非XHTML)環(huán)境下如果你的xss輸出點(diǎn)在<script>標(biāo)簽內(nèi),你采用了HTML實(shí)體編碼的形式,怎么可能觸發(fā)XSS漏洞呢?如果你不懂這個問題,也許你會做很多無用功。
0×02 瀏覽器中的詞法分析
熟悉編譯原理的讀者可以自由選擇快速略過第一第二段或者短暫復(fù)習(xí)一下。
關(guān)于一個計(jì)算機(jī)工作人員是否需要學(xué)習(xí)編譯原理這個話題,我相信大家各持己見。但是我相信如果你是要做一個優(yōu)秀的程序員或者是IT工作者,編譯原理不一定要精通,但是至少應(yīng)該有所了解,限于篇幅的原因,我并不打算在這里講太多的編譯原理的只是簡單提及一下讓大家知道編譯原理到底是干什么的,在瀏覽器中是怎么被應(yīng)用的。
Parser-Lexer Combination(解析器-詞法分析器)
這個結(jié)構(gòu)負(fù)責(zé)對html文檔進(jìn)行解析,解析的過程分為兩個過程:詞法分析和語法分析
本部分,主要講詞法分析部分
詞法分析就是將輸入的句子(語句,內(nèi)容)分解為有順序的單詞和符號:具體例子就是如果輸入1+2-3,那么經(jīng)過詞法分析,就應(yīng)該按順序得到五個token:分別是1(int),+(option),2(int),-(option),3(int)。然后得到的結(jié)果交給語法分析進(jìn)行上下文無關(guān)語法判別。
如果有興趣了解如何實(shí)現(xiàn)詞法分析,可以參考編譯原理及實(shí)踐這本書。
那么在瀏覽器中,詞法分析的特性還是值得注意的,例如,它會自動跳過HTML中的空格和換行或者制表符,這樣也就是有些條件下僅僅是多個空格或者換行符制表符就能起到過waf,的原理了,(但是現(xiàn)在這種bypass方法已經(jīng)很out了)。除此之外呢,在詞法分析中,也許還會忽略注釋部分,那么大家是不是又有一些想法了呢?那么,我們結(jié)合以前XSS的經(jīng)驗(yàn),筆者結(jié)合符號算法的簡單敘述,大家可以理解檢測一下自己的猜測是不是正確。
眾所周知,我們的瀏覽器解析html時,是把
<img src = 1/>
這個標(biāo)簽解析成
<
img
src
=
1
/
>
這六個符號(token)的。
那么僅僅就是這么簡單么?答案當(dāng)然是否定的。
解析過程簡單例子:
1. 在解析<這個符號以前,狀態(tài)是Data State
2. 然后解析到<的時候,解析狀態(tài)變?yōu)門ag open state,然后開始搜尋標(biāo)簽名,(在搜尋標(biāo)簽名的時候,我們要思考一個問題,<和標(biāo)簽名img并不是同一個token,他們顯然是分別進(jìn)行解析的,那么有沒有可能忽略掉<和img之間的空格或者換行什么的?這個問題,我相信很好找到答案。)
3. 找到標(biāo)簽名,狀態(tài)變?yōu)門ag name state,這個狀態(tài)就表示已經(jīng)識別了標(biāo)簽名,
4. 然后知道讀取到最近的一個>時,結(jié)束tag name state的狀態(tài),重新進(jìn)入Data State。
如果嵌套有標(biāo)簽的話重復(fù)上述解析步驟,關(guān)于</body>的部分,大同小異,只不過/符號會創(chuàng)建一個閉合標(biāo)簽的標(biāo)識,來表示一個標(biāo)簽的閉合。
但是!我要說的是但是!這個解析過程是相當(dāng)松散的。因?yàn)镠TML的歷史原因,導(dǎo)致HTML的模式千奇百怪,錯誤頻繁出現(xiàn),開發(fā)者程序員的水平參差不齊,HTML的不規(guī)范的特性。這個解析過程注定是相當(dāng)復(fù)雜的。舉個最簡單的例子。
<img src=x onerror=alert(1)>
你覺得這個元素可以被識別么?能彈窗么?既然這么問,那么答案肯定是肯定的。
<img src=http://pic.com/pic.jpg>
如果http://pic.com/pic.jpg這個圖片真實(shí)存在,那么,這個沒有引號的標(biāo)簽可以被識別么?
除此之外,還有很多很多的神奇的trick值得去探索。
0×03 HTML編碼與HTML解析
HTML實(shí)體編碼的出現(xiàn),解決了一個問題,例如<和>這兩個符號在HTML文檔中出現(xiàn)是非常不安全的,因?yàn)檫@標(biāo)志著標(biāo)簽的開始和結(jié)束,為了安全使用這些保留字符。開發(fā)人員使用了一套叫實(shí)體編碼的編碼策略,這類編碼以&開頭,以分號;結(jié)尾。
但是結(jié)合0×02的知識我們可以猜測,以“;”為分割符,在實(shí)際的處理中,由于瀏覽器解析器高度的容錯性,所有的可以成為分割符的符號放在結(jié)尾代替;當(dāng)然有可能可以正確分隔,那么這也就是著名的一個trick:HTML實(shí)體編碼最后的;可以省略,這就是原理所在。好,我們,接著講HTML實(shí)體編碼的一些有趣的東西。
在HTML編碼,中大家都知道一個應(yīng)該寫為“&#數(shù)字”或者“&#x十六進(jìn)制”,但是不為人知的可能就是后面的數(shù)字可以寫成Unicode,曾經(jīng)有點(diǎn)蛋疼的時候,筆者把所有的unicode字符用&#編碼的形式打了出來,看了一下有沒有什么有趣的符號。在《web之困》中,作者就舉例了一個有趣的符號:
那么讀者要問了,這個東西講的有什么意思呢?那么接下來就要說一些很明確的,也是很多有誤區(qū)的地方:HTML在哪里可以解析?整個HTML的文檔下都可以解析么?
得明確地講:HTML編碼要在Data state(標(biāo)簽外部和標(biāo)簽的text段)和標(biāo)簽內(nèi)的屬性值的位置解析,但是直接注意的是在特殊模式(這個問題將在下一段中解釋)下,即使是在Data state下,HTML編碼也照樣不會被解析。在0×02中,我們知道解析到HTML解析過程中,在遇到一對<和>的解析過程中,都是Tagname/open/close state,在這三個狀態(tài)中,HTML編碼也是不會被解碼的,也就意味著解析到標(biāo)簽屬性的值的時候自動切換進(jìn)了Data State,這些都是符合我們正確認(rèn)知的。
接下來我們來舉例(以Firefox為例):
看到下面的標(biāo)簽,有讀者就要問為什么沒有反斜杠?很簡單啊,瀏覽器識別一個標(biāo)簽我們在0×02部分講到的,只需要<作為標(biāo)簽的開始,并且>作為標(biāo)簽的結(jié)束,所以不一定需要有</tagname>,在HTML解析條件下也可以識別標(biāo)簽
我們在記事本中輸入這六個標(biāo)簽,讀者可以來猜一下哪些可以彈窗,哪些不能?
很顯然第一第二是完全可以的。
第三個沒有明顯寫明邊界,實(shí)際上這個和第二個的邊界處理是一樣的,默認(rèn)了邊界,(我們可以姑且認(rèn)為=和>是獨(dú)立的token,那么也就是說即使不用單引號或者雙引號或者反引號照樣可以起到邊界的作用,事實(shí)上卻是如此)
第四個人為加上了邊界,所以當(dāng)然是可以的,
第五個"就是引號,這里的引號在數(shù)據(jù)區(qū),也就相當(dāng)于onerror=”’ alert(1)’”
第六個,我們知道在非Data state段是不會HTML編碼解碼的,所以第六個破壞了屬性的結(jié)構(gòu)。
特殊模式:<style><script><textarea><xmp>這四個標(biāo)簽的text段按理說也是Data state但是沒辦法進(jìn)行HTML編碼的解析,原因就是他們處于特殊模式,在這個模式中,相當(dāng)于是啟動了別的解析器,也就是為了處理別的代碼或者特定文本,關(guān)閉了HTML編碼的解析。
接下來我們嘗試一下HTML到底能不能在<script>中解析:
大家看到了,源碼是這樣的,顯然是沒有辦法解析HTML編碼的。
作為對比我們再看一下下面的情況
這樣我們就發(fā)現(xiàn)了普通條件下的在標(biāo)簽的text段的確是發(fā)生了HTML編碼的解析。
0×04 常見誤區(qū)
我既然寫在普通的Data State段,而且提示也提示出了<script>alert(1)<script>但是為什么不會彈框呢?可能有讀者還是會有這個問題。
這里需要提醒大家的是:HTML編碼(HTML實(shí)體編碼)的出現(xiàn),是為了防止保留符號與顯示字符的沖突。
那么我們解析原因就很簡單了:也就是說<script>alert(1)</script>這個字符串實(shí)際上只為了顯示,而不執(zhí)行,js代碼的執(zhí)行是放在HTML編碼之后,而且必須位于可以執(zhí)行的地方對么?大家想一下,如果放在<a>標(biāo)簽內(nèi),沒人指示執(zhí)行JS代碼,而且顯示<script>alert(1)</script>這個時候HTML解析器只是把它顯示出來并不會執(zhí)行(如果讀者這里有點(diǎn)懵逼,那么請返回看0×01部分)。
然后為什么標(biāo)簽屬性值的部分是可以執(zhí)行的呢?很簡單,因?yàn)閛nxxxx的函數(shù)都是時間處理函數(shù),的確屬于HTML標(biāo)準(zhǔn)的屬性值,但是大家可以理解為這是JS特定函數(shù)或者特定功能的執(zhí)行入口,那么在解析的時候,首先把HTML標(biāo)簽屬性的值當(dāng)作數(shù)據(jù)解析以后(解析HTML代碼),然后交給JS引擎,然后執(zhí)行。這樣就可以得到JS的執(zhí)行結(jié)果。
0×05 瀏覽器有趣的容錯行為
我們接下來還是以一個標(biāo)簽為例。來總結(jié)一下瀏覽器是有多么強(qiáng)大的容錯性。
對于這樣一個標(biāo)簽,我們多多少少看起來還有點(diǎn)別扭。但是經(jīng)過0×02的講解,我相信大家腦子里應(yīng)該是已經(jīng)把它分解成了很多個token,而且,可以很輕易的分辨出這個tag是完全可以正常工作的。首先我們從開頭一點(diǎn)一點(diǎn)來解釋:
1. 在IE瀏覽器中,你可以在img中間加入NULL字符,而且還可以解析成功。
2. 在img和src還有src=s和title之間的兩個邊界,你完全可以用別的符號來替換邊界
有圖為證:
換成\t仍然可以解析成功,也就是并不是必須用空格或者\(yùn)t的對吧。換成\n照樣可以成功:
至于還有什么符號還可以,嗯哼,這就需要讀者自己嘗試了(什么難道你要自己一個一個試?)
1. 大家注意我在onerror和class參數(shù)之間沒有空格或者其他分隔符,但是仍然可以執(zhí)行成功,為什么?這個問題我在前面部分多次提到。
2. 屬性的值的邊界應(yīng)該用什么來確定?單引號,雙引號,反引號,還有呢?這里也是讀者可以自己動手去嘗試的。
0×06 結(jié)語
讀者要明白,瀏覽器之間都是有差異的,尤其是IE和其他類型的瀏覽器,那么具體的差異的內(nèi)容,大家可以fuzz一下,當(dāng)然有一些資料推薦給大家使用的:《web application obfuscation》,《web之困》。本文簡單談一談HTML編碼這些問題就已經(jīng)有了這么長的篇幅。如果有機(jī)會,筆者將在以后的文章中為大家講解一下其他的編碼部分(URL編碼和JS編碼)
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。