2012-12-08 13 views
5

Załaduję plik tekstowy z nowymi znakami i przesyłam go do html/templates.html/templates - Zastępując znaki nowej linii za pomocą <br>

Zamieniając w załadowanym ciągu \n z <br>, są one przekształcane przez szablon do html &lt;br&gt; i wyświetlane w przeglądarce, zamiast powodować powrót linii.

Jak mogę zmienić to zachowanie bez przełączania na text/templates (która nie ma ochrony XSS)?

Odpowiedz

6

Wydaje można uruchomić template.HTMLEscape() na tekst, aby go najpierw zdezynfekować, a następnie wykonaj \ n do
podstawienia, któremu ufasz, a następnie użyj go jako danych z prefiksu i zaufanych szablonów.

Aktualizacja: Rozszerzenie na przykład Kocka, jest to, co miałem na myśli:

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

Wyjście jest

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

i tekstu wydanego w przeglądarce jest

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

Nie wiem, gdzie zastępujesz \n dla <br>, ale jeśli jest w ruchu, możesz rzucić ciąg znaków jako template.HTML, aby nie był chroniony.

Patrz: http://golang.org/pkg/html/template/#HTML

Jeśli jest w szablonie, nie powinno być rurociąg dostępne {{. | html}}

+0

nie może oddać go do 'template.HTML' ponieważ mój ciąg nie jest bezpieczny. Czy mógłbyś rozwinąć sztuczkę z Pileline? Wielkie dzięki –

+2

jeśli łańcuch nie jest bezpieczny, to potok nie pomoże. Spróbuj podzielić ciąg na '\ n" 'i przekazując wynikowy plaster do szablonu. Użyj 'range', aby wydrukować ciąg znaków i wstaw'
'. Na przykład: 'Arr: = stringi.Split (myString," \ n ")' w kodzie go i '{{range Arr}} {{.}}
{{end}}' w szablon. – dskinner

+1

@dskinner, wiem, że jest późno, ale powinieneś napisać swoje jako pełną odpowiedź. To znacznie czystsze rozwiązanie. – Nashenas

2

Można to zrobić tak:

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

To właściwie właściwa ścieżka --- ale zobaczyłem, że dane wejściowe nie są zapisywane, co wymaga więcej przetwarzania, co poprawnie zrobiono w zaakceptowanej odpowiedzi. – JohnDoe

1

Nie ma potrzeby przechodzić cały szablon jako niebezpieczny szablonu (i to jest złe praktyki).

Powinieneś przekazać mapę do swojego szablonu i tylko jawnie "niebezpieczne" elementy, które chcesz użyć jako takie, np.

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) 
} 

Plony:

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

Chociaż pomysł jest właściwy, implementacja jest błędna: oznaczenie ciągu jako "bezpiecznego" poprzez zawijanie go w 'template.HTML (...)' wyłącza wszystkie inne znaki ucieczki, np. wszelkie jednoliniowe '

Powiązane problemy