2012-12-08 14 views
5

改行を含むテキストファイルをロードして、html/templatesに渡します。html/templates - 改行を<br>に置き換えます。

\nをロードされた文字列に置き換えると、テンプレートによってHTML &lt;br&gt;にエスケープされ、行が返される代わりにブラウザに表示されます。

text/templates(XSS保護機能はありません)に切り替えることなくこの動作を変更するにはどうすればよいですか。

答えて

6

、その後行います\ n〜
代理人が信頼する代入を行い、それをエスケープされた信頼できるテンプレートデータとして使用します。

更新:Kockaの例を拡張し、これは私が考えていたものです:

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

は、利用可能パイプラインがあるはず、あなたがそれをサニタイズする最初のテキストにtemplate.HTMLEscape()を実行することができそうです{{. | html}}

+0

私の文字列が安全ではないので、私はtemplate.HTML' 'にキャストすることはできません。 杭打ちのトリックを詳しく説明できますか?ありがとうたくさん –

+2

もし文字列が安全でないなら、パイプラインは助けにならないでしょう。文字列を '" \ n "'に分割し、結果のスライスをテンプレートに渡してみてください。 'range'を使用して文字列を印刷し、'
'を挿入してください。例: goコマンドの場合、Arr:= strings.Split(myString、 "\ n") 'と {{range arr}} {{。}}
{{end}}'テンプレート。 – 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'の任意の一行の'

関連する問題