[enh] use html template for injected html snippets

git-svn-id: file:///srv/svn/repo/yukari/trunk@121 f3bd38d9-da89-464d-a02a-eb04e43141b5
This commit is contained in:
asciimoo 2020-07-14 21:22:08 +00:00
parent 53dfdf3070
commit 5d5b7b413f

View File

@ -9,6 +9,7 @@ import (
"errors" "errors"
"flag" "flag"
"fmt" "fmt"
"html/template"
"io" "io"
"log" "log"
"mime" "mime"
@ -186,31 +187,18 @@ type RequestConfig struct {
BaseURL *url.URL BaseURL *url.URL
} }
var HTML_FORM_EXTENSION string = `<input type="hidden" name="mortyurl" value="%s" /><input type="hidden" name="mortyhash" value="%s" />` type HTMLBodyExtParam struct {
BaseURL string
HasMortyKey bool
}
var HTML_BODY_EXTENSION string = ` type HTMLFormExtParam struct {
<input type="checkbox" id="mortytoggle" autocomplete="off" /> BaseURL string
<div id="mortyheader"> MortyKey string
<form method="get"> }
<label for="mortytoggle">hide</label>
<span><a href="/">Morty Proxy</a></span>
<input type="url" value="%s" name="mortyurl" readonly="true" />
This is a <a href="https://github.com/asciimoo/morty">proxified and sanitized</a> view of the page, visit <a href="%s" rel="noreferrer">original site</a>.
</form>
</div>
<style>
body{ position: absolute !important; top: 42px !important; left: 0 !important; right: 0 !important; bottom: 0 !important; }
#mortyheader { position: fixed; margin: 0; box-sizing: border-box; -webkit-box-sizing: border-box; top: 0; left: 0; right: 0; z-index: 2147483647 !important; font-size: 12px; line-height: normal; border-width: 0px 0px 2px 0; border-style: solid; border-color: #AAAAAA; background: #FFF; padding: 4px; color: #444; height: 42px; }
#mortyheader p { padding: 0 0 0.7em 0; display: block; }
#mortyheader a { color: #3498db; font-weight: bold; display: inline; }
#mortyheader label { text-align: right; cursor: pointer; position: fixed; right: 4px; top: 4px; display: block; color: #444; }
#mortyheader > form > span { font-size: 24px; font-weight: bold; margin-right: 20px; margin-left: 20px; }
input[type=checkbox]#mortytoggle { display: none; }
input[type=checkbox]#mortytoggle:checked ~ div { display: none; visibility: hidden; }
#mortyheader input[type=url] { width: 50%%; padding: 4px; font-size: 16px; }
</style>
`
var HTML_FORM_EXTENSION *template.Template
var HTML_BODY_EXTENSION *template.Template
var HTML_HEAD_CONTENT_TYPE string = `<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> var HTML_HEAD_CONTENT_TYPE string = `<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="referrer" content="no-referrer"> <meta name="referrer" content="no-referrer">
@ -255,6 +243,37 @@ func init() {
FaviconBase64 := "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABmJLR0T///////8JWPfcAAAACXBIWXMAAABIAAAASABGyWs+AAAAF0lEQVRIx2NgGAWjYBSMglEwCkbBSAcACBAAAeaR9cIAAAAASUVORK5CYII" FaviconBase64 := "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABmJLR0T///////8JWPfcAAAACXBIWXMAAABIAAAASABGyWs+AAAAF0lEQVRIx2NgGAWjYBSMglEwCkbBSAcACBAAAeaR9cIAAAAASUVORK5CYII"
FAVICON_BYTES, _ = base64.StdEncoding.DecodeString(FaviconBase64) FAVICON_BYTES, _ = base64.StdEncoding.DecodeString(FaviconBase64)
var err error
HTML_FORM_EXTENSION, err = template.New("html_form_extension").Parse(
`<input type="hidden" name="mortyurl" value="{{.BaseURL}}" /><input type="hidden" name="mortyhash" value="{{.MortyKey}}" />`)
if err != nil {
panic(err)
}
HTML_BODY_EXTENSION, err = template.New("html_body_extension").Parse(`
<input type="checkbox" id="mortytoggle" autocomplete="off" />
<div id="mortyheader">
<form method="get">
<label for="mortytoggle">hide</label>
<span><a href="/">Morty Proxy</a></span>
<input type="url" value="{{.BaseURL}}" name="mortyurl" {{if .HasMortyKey }}readonly="true"{{end}} />
This is a <a href="https://github.com/asciimoo/morty">proxified and sanitized</a> view of the page, visit <a href="{{.BaseURL}}" rel="noreferrer">original site</a>.
</form>
</div>
<style>
body{ position: absolute !important; top: 42px !important; left: 0 !important; right: 0 !important; bottom: 0 !important; }
#mortyheader { position: fixed; margin: 0; box-sizing: border-box; -webkit-box-sizing: border-box; top: 0; left: 0; right: 0; z-index: 2147483647 !important; font-size: 12px; line-height: normal; border-width: 0px 0px 2px 0; border-style: solid; border-color: #AAAAAA; background: #FFF; padding: 4px; color: #444; height: 42px; }
#mortyheader p { padding: 0 0 0.7em 0; display: block; }
#mortyheader a { color: #3498db; font-weight: bold; display: inline; }
#mortyheader label { text-align: right; cursor: pointer; position: fixed; right: 4px; top: 4px; display: block; color: #444; }
#mortyheader > form > span { font-size: 24px; font-weight: bold; margin-right: 20px; margin-left: 20px; }
input[type=checkbox]#mortytoggle { display: none; }
input[type=checkbox]#mortytoggle:checked ~ div { display: none; visibility: hidden; }
#mortyheader input[type=url] { width: 50%; padding: 4px; font-size: 16px; }
</style>
`)
if err != nil {
panic(err)
}
} }
func (p *Proxy) RequestHandler(ctx *fasthttp.RequestCtx) { func (p *Proxy) RequestHandler(ctx *fasthttp.RequestCtx) {
@ -490,12 +509,9 @@ func popRequestParam(ctx *fasthttp.RequestCtx, paramName []byte) []byte {
if param == nil { if param == nil {
param = ctx.PostArgs().PeekBytes(paramName) param = ctx.PostArgs().PeekBytes(paramName)
if param != nil { ctx.PostArgs().DelBytes(paramName)
ctx.PostArgs().DelBytes(paramName)
}
} else {
ctx.QueryArgs().DelBytes(paramName)
} }
ctx.QueryArgs().DelBytes(paramName)
return param return param
} }
@ -639,8 +655,12 @@ func sanitizeHTML(rc *RequestConfig, out io.Writer, htmlDoc []byte) {
if rc.Key != nil { if rc.Key != nil {
key = hash(urlStr, rc.Key) key = hash(urlStr, rc.Key)
} }
fmt.Fprintf(out, HTML_FORM_EXTENSION, urlStr, key) err := HTML_FORM_EXTENSION.Execute(out, HTMLFormExtParam{urlStr, key})
if err != nil {
if DEBUG {
fmt.Println("failed to inject body extension", err)
}
}
} }
case html.EndTagToken: case html.EndTagToken:
@ -648,7 +668,16 @@ func sanitizeHTML(rc *RequestConfig, out io.Writer, htmlDoc []byte) {
writeEndTag := true writeEndTag := true
switch string(tag) { switch string(tag) {
case "body": case "body":
fmt.Fprintf(out, HTML_BODY_EXTENSION, rc.BaseURL.String(), rc.BaseURL.String()) p := HTMLBodyExtParam{rc.BaseURL.String(), false}
if len(rc.Key) > 0 {
p.HasMortyKey = true
}
err := HTML_BODY_EXTENSION.Execute(out, p)
if err != nil {
if DEBUG {
fmt.Println("failed to inject body extension", err)
}
}
case "style": case "style":
state = STATE_DEFAULT state = STATE_DEFAULT
case "noscript": case "noscript":