顯示具有 html 標籤的文章。 顯示所有文章
顯示具有 html 標籤的文章。 顯示所有文章

5/31/2007

Markaby:惡趣味的逆襲

有些東西你明知道是錯的,但是還是會去做,只是因為那樣做很爽。

不是說你很邪惡,而只是因為有時候作壞事本身就是一件很有趣的事情。像是蹺課出去打撞球,像是上班偷懶,像是捉弄朋友....等等雖然明知道本身是不對的事情,但是依舊無法抗拒這種快感。第一次看到 Markaby,心中的 OS 是「妖孽呀,這是網頁設計的邪道呀」。但是最近有機會碰到高手寫的 Markaby code ,頓時發覺有點沈溺其中無法自拔(果然是邪道,才會有毒品的快感)。或許這又是一個明知不對,但是又令人忍不住去碰的小誘惑。

敝人小弟在下我曾經寫過HTML?New Template System ?,裡面有提到
Ruby 統一全世界當然是一個美好的夢想,畢竟我是100%原汁的 Ruby 派。但是當你在商業應用上,版面設計通常交給美工,他們只需要會 Dreamweaver 之類的東西
這時候,難道你要教美工 Ruby 程式設計?
所以,除非 Dreamweaver 或是 Frontpage 支援 Ruby @@!,不然大家還是先把 HTML 當成網頁程式設計的最大公約數好了。
因為考慮到美工人員不太會去管程式,程式也沒這個 sense 去碰美工,所以所謂的 template 正道,就是「美工歸美工,程式歸程式」。基本要求是 HTML 版面跟 Rails 程式分開,美工好做事,程式也好修改。

但是 Markaby 就是一個相當詭異的存在,他是一個使用 Ruby Code 來撰寫 html 的方式。他是一個 Rails Plugin ,安裝方式是
 script/plugin install http://code.whytheluckystiff.net/svn/markaby/trunk
rhtml 跟 markaby 是可以兩者並行的,請先將你的 markaby file 都從 .rhtml 改成 .mab 的名字,這樣 rails 就可以知道這是 markaby 的檔案了。

撰寫範例是這樣

h1 'Listing products'

table.editor.classic do
tr do
for column in Product.content_columns
th column.human_name
end
end

for product in @products
tr do
for column in Product.content_columns
td product.send(column.name)
end
td { link_to 'Show', :action => 'show', :id => product }
td { link_to 'Edit', :action => 'edit', :id => product }
td { link_to 'Destroy', { :action => 'destroy', :id => product }, :confirm => 'Are you sure?' }
end
end
end

link_to 'Previous page', { :page => @product_pages.current.previous } if @product_pages.current.previous
link_to 'Next page', { :page => @product_pages.current.next } if @product_pages.current.next

br

link_to 'New product', :action => 'new'
裡面有很多 html tag 跟 Ruby code,Rails helper。裡面看不到煩人的 <% %> 等符號,只有讓人興奮的 Ruby code。

好處呢?

就是一個爽字形容,還有另外一種自己已經成為高手的錯覺。

壞處呢?

你沒辦法用美工改好給你的 HTML code ,你必須要求美工使用 CSS 來做所有排版的工作,不然合作起來也非常累。另外一個壞處是,交接的時候交接的人會很不高興,這是哪門子的版面 code ,要我怎麼看呀。

該不該用呢?

就實際面來說,沒有任何實用價值。但是你也知道,有些東西你明知道是錯的,但是還是會去做,只是因為他很爽。所以夜深人靜的某個夜晚,我依舊偷偷使用 Markaby 來寫我的某個小網頁 :p

12/27/2006

Hemidemi 的首頁書籤討論的 HTML 碼

如果仔細觀看 Hemidemi 的首頁,你會發現他有時候書籤最新討論會出現下面的狀態

會出現類似圖中糯米團寫的
其實這是抄襲自"獵人"的<a href=& quot
如此 HTML 碼的原因很簡單。在顯示書籤討論的內容, Hemidemi 是允許一些 HTML Tags,來充實討論區的版面。但是在首頁上,站長應該是怕 HTML Tags 破壞版面,所以用類似 h() 或是自己寫一個 filter 的方式,把所有的< >都改成了 & gt; & lt;," 改成 & quot,用來保護版面的乾淨跟安全性。這些議題其實都在本 Blog 的 HTML Filter 系列討論過了。但是Hemidemi 首頁的 HTML 碼實在是太難看了,有沒有方式可以只顯示 HTML Tag 的內文即可。

當然有,在 Ruby on Rails 就是 strip_tags() 這個 function,他會將所有
<a href='http://www.example.com'>lala</a>
轉成只有內文
lala

就上面的實際範例,糯米團寫的
其實這是抄襲自"獵人"的<a href="http://zh.wikipedia.org/wiki/%E5%BF%B5%E8%83%BD%E5%8A%9B">念能力</a>! XD

就會被 strip_tags 改成只顯示
其實這是抄襲自"獵人"的念能力! XD
這樣在首頁顯示就好多了。

眾所皆知,Hemidemi 是用 Ruby on Rails 寫的,如果站長看到的話,順手改一下吧:)

UPDATE: 葛力好快的動作呀。

11/22/2006

HTML Filter 3: XSS

講了那麼多 HTML Filter 的例子 例子2,回到一個問題?如果照著之前的程式,有沒有辦法防範 XSS ?我現在給的答案是
不容易
為什麼?難道 Rails 那麼爛?錯了,看看這個表吧,當你的站遇到 Extra dot for absolute DNS 這種攻擊。
<IMG """><SCRIPT>alert("XSS")</SCRIPT>">
我們發現,有太多玩法可以放 XSS,而濾掉特定 tag 方式幾乎行不通,因為我們還是希望開放某些有用的 tag 像是 a 或是 img。但是我們可以減少這種可能發生率
  1. 使用 white list filter ,盡量少用 black list,whitelist 就是僅僅開放某些 tag ,blacklist 就是僅僅關閉某些 tag。我之前的 html filter 就是 white list 的。
  2. href 跟 src 裡面要檢查 javascript 的欄位
  3. 如果沒必要開放 tag ,盡量使用 h 通殺
延伸閱讀
  1. XSS 筆記
  2. XSS 列表

11/16/2006

HTML Fliter Part(2):yml 化的 sanitize

根據上一篇 HTML Filter ,我們發現到這個 sanitize 很好用。但是,但是,他的 okTags 太醜了,我不喜歡。
def sanitize( html, okTags='a href, b, br, i, p' )
我在想,能不能更加的 Ruby 化一點,所以我就花了點時間改寫一下程式,變成了新版的 sanitize。我們將 allow 的 tag 跟 attribute 寫在 yml 裡面,然後執行時 load 進去,這樣似乎比較結構化一點,並且可以在 Rails 使用。License 是 MIT。

首先,你先寫一個 allow_tags.yml 的 file ,原本 okTags = 'a href target, b, br, p, i' 變成了
a:
- href
- target
b:
br:
p:
i:
a: 代表你接受 a 這個 tag ,後面加上 -href 代表你接受 a tag 底下的 href attribute ,如果你還要加一個 target attribute 就是加一個 -target ,不難懂吧。

如果你在 Ruby on Rails 裡面,建議放在 config 下面。然後,將這段程式(nopaste 版本)放到任何可以 loading 的地方即可。

HTML Filter

一般來說,通常使用者 input 的 field 都會作一些 filter 的動作,避免你塞一些危險的 HTML code (script之類)進去。而這部份 Ruby on Rails 作法很簡單,就是在前面加上一個 h() 即可。h 在Ruby on Rails 作什麼事情呢?他是 html_escape 的 alias ,他會將所有的 < 還有 > 變成 & lt; ,& gt;,比如 <sctipt>alert('a'); </sctipt> 會變成
& lt;sctipt& gt;alert('a'); & lt;/sctipt& gt;
這樣你就完全作不了亂啦,因為所有 tag 都不見了。但是這樣通常嫌太過嚴格一點了,有時候我們會希望開放一些字型大小,顏色的tag 給你用,這時候 h() 通殺的特性會讓一切都變得很麻煩。所以這時候 Ruby on Rails 就出現 sanitize() 這個 function,根據 Ruby on Rails 的api 上面解釋
Sanitizes the given HTML by making form and script tags into regular text, and removing all "onxxx" attributes (so that arbitrary Javascript cannot be executed). Also removes href attributes that start with "javascript:".
他會砍掉 script 這個 tag ,以及 onClick onLoad 之類的 attribute ,你沒有機會執行 javascript ,那就會讓你 key-in 任何東西都如 sanitize 字面上一樣『完全無害』。但是,Ruby on Rails 預設的 sanitize 管制方式又有點大方,你還是可以塞一些 div 或是 iframe 之類的 tag 讓你的網站版面爛掉。

所以我們需要一個可以自訂的 HTML Filter ,可以自由指定我們放行那些 tag 。這時候我發現了這個網頁,這是 Brad Choate's 寫的 perl 函式 sanitize_html 的 Ruby porting,你可以到這裡下載 Ruby 的版本。這只有一個函式,請將這個函式放在任何可以 loading 的地方,然後使用
sanitize( HTML 程式碼 )
即可。我們來仔細研究一下怎麼使用,他的第一行
def sanitize( html, okTags='a href, b, br, i, p' )
okTags 代表的意思是就是他允許的 tag ,目前有 a ,b , br , i , p 之類的 tag 。如果你輸入 <iframe>aaa</iframe>之類的不允許的 code ,他會出現
aaa
這樣的結果,所有不被允許的 tag 一律被濾掉。如果你想加入 span,font 這個兩個 tag ,那就將他變成
def sanitize( html, okTags='a href, b, br, i, p, span, font' )
以此類推,很簡單吧。至於第一個的 a href 代表什麼意思呢?第一個 a 代表 sanitize 允許 a 這個 tag ,第二個 href 跟第一個 a 中間沒有逗號分開,代表 sanitize 允許 a 這個 tag 使用 href 這個 attribute。你要是不信的話,打入 <a href="http://lightyror.blogspot.com" target="_blank">Haha</a>之類的程式,他只會出現
<a href="http://lightyror.blogspot.com">Haha</a>
只有 href 這個 attribute 會被保留,其他的刪無赦 XD。如果你想讓 a 這個 tag 加入 target attribute ,那麼就這樣寫吧。
def sanitize( html, okTags='a href target, b, br, i, p' )
如此他就會保留 href 跟 target 這兩個 attribute。最後,當我們輸入這樣的 HTML <a href="http://lightyror.blogspot.com">Haha 有頭無尾的 html code ,神奇的是他居然會補齊 tag 成
<a href="http://lightyror.blogspot.com">Haha</a>
恩,這個東西實做相當完整,看起來十分有用。

9/18/2006

HTML?New Template System ?

現行 Scripting Language 不管PHP,ASP,或是ERB大多是採用
              <td width="100%"> <b><%= link_to '請按此' , :action => 'index' %></b></td>
類似這樣的形式。也就是 HTML 為主,並且在裡面嵌入 scripting language code。Rails ERB也是這樣的作法,不過Ruby 愛好者有一種不知道是好還是壞的想法
VIVA ,Ruby 統一全世界
Javascript 用 RJS 併吞掉、SQL 用 ActiveRecord and Migrate 併吞掉、Web Service 用 Action Web Service、Mail 用 Action Mailer、甚至Web Server 都有 Ruby 版本( Webricks 還有 Mongrel )。這些我都相當的贊成,因為 Javascript 跟 SQL 的混亂已經嚴重影響到程式設計師
今天卻發現 HAML and MarkBy,可以讓 HTML 也危在旦夕(笑)。

HAML 就是原本的RHTML
<small><%= item.body %></small>
變成
%small= item.body
而MarkBy更是厲害
require 'markaby'

mab = Markaby::Builder.new
mab.html do
head { title "Boats.com" }
body do
h1 "Boats.com has great deals"
ul do
li "$49 for a canoe"
li "$39 for a raft"
li "$29 for a huge boot that floats and can fit 5 people"
end
end
end
puts mab.to_s
如此用 Ruby 寫出 HTML @@!。對岸這對於這方面的態度是將這些東西,歸類在近乎奇淫技巧 上面。

我的感覺是這樣

還記得 OSDC 2006 in TW上面,Ingy 在講到Wiki語法混亂的問題時(只憑記憶,有錯請見諒)
有人說 Wiki 語法太多太亂,需要 Standard 統一 ,但是依我所見,其實現在早就有 WIKI Standard 了,那就是 HTML
Ruby 統一全世界當然是一個美好的夢想,畢竟我是100%原汁的 Ruby 派。但是當你在商業應用上,版面設計通常交給美工,他們只需要會 Dreamweaver 之類的東西
這時候,難道你要教美工 Ruby 程式設計?
所以,除非 Dreamweaver 或是 Frontpage 支援 Ruby @@!,不然大家還是先把 HTML 當成網頁程式設計的最大公約數好了。