2012-12-08 148 views
5

我正在加載一個文本文件,其中有換行符,並將其傳遞給html/templateshtml/templates - 用<br>代替換行

\n替換爲加載字符串中的<br>,它們被模板轉義爲html &lt;br&gt;並顯示在瀏覽器中,而不是導致行返回。

如何在不切換到text/templates(沒有XSS保護)的情況下更改此行爲?

回答

6

看來,你可以在你的文本串template.HTMLEscape()第一次消毒,然後做\ n到您信任的替代品
,然後將其用作預先轉義和可信的模板數據。

更新:擴大對柯卡的例子,這是我腦子裏想的:

package main 

import (
    "html/template" 
    "os" 
    "strings" 
) 

const page = `<!DOCTYPE html> 
<html> 
    <head> 
    </head> 
    <body> 
    <p>{{.}}</p> 
    </body> 
</html>` 

const text = `first line 
<script>dangerous</script> 
last line` 

func main() { 
    t := template.Must(template.New("page").Parse(page)) 
    safe := template.HTMLEscapeString(text) 
    safe = strings.Replace(safe, "\n", "<br>", -1) 
    t.Execute(os.Stdout, template.HTML(safe)) // template.HTML encapsulates a known safe HTML document fragment. 
} 

http://play.golang.org/p/JiH0uD5Zh2

輸出是

<!DOCTYPE html> 
<html> 
    <head> 
    </head> 
    <body> 
    <p>first line<br>&lt;script&gt;dangerous&lt;/script&gt;<br>last line</p> 
    </body> 
</html> 

和文本瀏覽器中呈現爲

first line 
<script>dangerous</script> 
last line 
3

不知道你在哪裏爲<br>\n但如果是在旅途中,你可以投字符串作爲template.HTML,所以它沒有逃過。

參見:http://golang.org/pkg/html/template/#HTML

如果它在一個模板,應該有可用的管道,{{. | html}}

+0

因爲我的字符串是不是安全的,我不能把它轉換成'template.HTML'。 你能詳細說明一下釣魚技巧嗎?非常感謝 –

+2

如果字符串不安全,那麼管道也無濟於事。嘗試在'「\ n」'上分割字符串並將生成的片段傳遞到模板中。使用'range'打印字符串並插入'
'。例如: 'Arr:= strings.Split(myString,「\ n」)''在代碼中,並且 '{{range Arr}} {{。}}
{{end}}'in the模板。 – dskinner

+1

@dskinner,我知道已經晚了,但你應該寫出你的答案。這是一個更清潔的解決方案。 – Nashenas

2

你可以這樣說:

package main 

import (
    "html/template" 
    "os" 
) 

const page = `<!DOCTYPE html> 
<html> 
    <head> 
    </head> 
    <body> 
    <p>{{.}}</p> 
    </body> 
</html>` 

func main() { 
    t := template.Must(template.New("page").Parse(page)) 
    t.Execute(os.Stdout, template.HTML("<br>")) 
} 

Try it out!

+0

這實際上是正確的軌道---但看到,輸入不是保存,這需要更多的處理,正如接受的答案中所做的那樣。 – JohnDoe

1

沒有必要通過整個模板作爲一個不安全的模板(這是不好的做法)。

您應該將地圖傳遞給您的模板,並且只顯式「不安全」您要使用的元素,例如。

package main 

import "bytes" 
import "fmt" 
import "html/template" 
import "strings" 

var input = ` 
    {{ define "LAYOUT" }} 
    <html> 
     <body> 
     {{ template "CONTENT" . }} 
     </body> 
    </html> 
    {{ end }} 

    {{ define "CONTENT" }} 
    Unsafe content: {{ .Unsafe }} 
    Newlines converted to <br/> follow: 
    {{ .Normal }} 
    {{ end }} 

    {{ template "LAYOUT" . }} 
` 

var other = ` 
    Hello 
    World 
    Again 
` 

var other2 = ` 
    <script>alert("Owned!");</script> 
` 

func main() { 

    var t, err = template.New("sample").Parse(input) 
    if err != nil { 
     panic(err) 
    } 

    var fixed = strings.Replace(other, "\n", "\n<br/>", -1) 
    var model = map[string]interface{}{ 
     "Normal": template.HTML(fixed), 
     "Unsafe": other2, 
    } 

    var out bytes.Buffer 
    t.Execute(&out, model) # <--- !! Notice the model is NOT an HTML type. 

    var raw = out.String() 
    fmt.Printf("%s", raw) 
} 

產量:

Unsafe content: &lt;script&gt;alert(&#34;Owned!&#34;);&lt;/script&gt; 

Newlines converted to <br/> follow: 
<br/> Hello 
<br/> World 
<br/> Again 
<br/> 

    </body> 
</html> 
+1

雖然這個想法是正確的,但實現是錯誤的:通過將字符串包裝在「template.HTML(...)」中禁用所有其他轉義,例如將字符串標記爲「安全」。 'other'中的任何單行'