diff options
author | Feuerfuchs <git@feuerfuchs.dev> | 2019-11-16 09:59:03 +0100 |
---|---|---|
committer | Feuerfuchs <git@feuerfuchs.dev> | 2019-11-16 09:59:03 +0100 |
commit | 67571c49c119993ce553bec68c87e59332b5e03c (patch) | |
tree | 458efc711f3cf99a55a4ab3aba4f8cdf1cc3ac5d | |
parent | Fixed some issues with Gemini (diff) | |
download | gopherproxy-67571c49c119993ce553bec68c87e59332b5e03c.tar.gz gopherproxy-67571c49c119993ce553bec68c87e59332b5e03c.tar.bz2 gopherproxy-67571c49c119993ce553bec68c87e59332b5e03c.zip |
Gemini: Add support for charset MIME parameter
-rw-r--r-- | go.mod | 2 | ||||
-rw-r--r-- | go.sum | 1 | ||||
-rw-r--r-- | gopherproxy.go | 48 | ||||
-rw-r--r-- | libgemini.go | 14 |
4 files changed, 40 insertions, 25 deletions
@@ -7,6 +7,8 @@ require ( | |||
7 | github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 | 7 | github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 |
8 | github.com/prologic/go-gopher v0.0.0-20181230133552-0c68ed5f58b0 | 8 | github.com/prologic/go-gopher v0.0.0-20181230133552-0c68ed5f58b0 |
9 | github.com/temoto/robotstxt v0.0.0-20180810133444-97ee4a9ee6ea | 9 | github.com/temoto/robotstxt v0.0.0-20180810133444-97ee4a9ee6ea |
10 | golang.org/x/net v0.0.0-20190311183353-d8887717615a | ||
11 | golang.org/x/text v0.3.0 | ||
10 | ) | 12 | ) |
11 | 13 | ||
12 | go 1.13 | 14 | go 1.13 |
@@ -83,6 +83,7 @@ golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJ | |||
83 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | 83 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
84 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= | 84 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= |
85 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | 85 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
86 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||
86 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | 87 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= |
87 | golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | 88 | golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= |
88 | golang.org/x/tools v0.0.0-20190404132500-923d25813098 h1:MtqjsZmyGRgMmLUgxnmMJ6RYdvd2ib8ipiayHhqSxs4= | 89 | golang.org/x/tools v0.0.0-20190404132500-923d25813098 h1:MtqjsZmyGRgMmLUgxnmMJ6RYdvd2ib8ipiayHhqSxs4= |
diff --git a/gopherproxy.go b/gopherproxy.go index ab8e906..65c8f89 100644 --- a/gopherproxy.go +++ b/gopherproxy.go | |||
@@ -10,11 +10,15 @@ import ( | |||
10 | "io" | 10 | "io" |
11 | "io/ioutil" | 11 | "io/ioutil" |
12 | "log" | 12 | "log" |
13 | "mime" | ||
13 | "net/http" | 14 | "net/http" |
14 | "net/url" | 15 | "net/url" |
15 | "regexp" | 16 | "regexp" |
16 | "strings" | 17 | "strings" |
17 | 18 | ||
19 | "golang.org/x/net/html/charset" | ||
20 | "golang.org/x/text/transform" | ||
21 | |||
18 | "github.com/temoto/robotstxt" | 22 | "github.com/temoto/robotstxt" |
19 | 23 | ||
20 | "github.com/prologic/go-gopher" | 24 | "github.com/prologic/go-gopher" |
@@ -133,7 +137,7 @@ func renderGopherDirectory(w http.ResponseWriter, tpl *template.Template, assetL | |||
133 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, out, "", false, "gopher"}) | 137 | }{title, fmt.Sprintf("%s/%s", hostport, uri), assetList, out, "", false, "gopher"}) |
134 | } | 138 | } |
135 | 139 | ||
136 | func parseGeminiDocument(response *GeminiResponse, uri string, hostport string) (items []Item) { | 140 | func parseGeminiDocument(body *bytes.Buffer, uri string, hostport string) (items []Item) { |
137 | baseUrl, err := url.Parse(fmt.Sprintf( | 141 | baseUrl, err := url.Parse(fmt.Sprintf( |
138 | "gemini://%s/%s", | 142 | "gemini://%s/%s", |
139 | hostport, | 143 | hostport, |
@@ -143,8 +147,7 @@ func parseGeminiDocument(response *GeminiResponse, uri string, hostport string) | |||
143 | return []Item{} | 147 | return []Item{} |
144 | } | 148 | } |
145 | 149 | ||
146 | scanner := bufio.NewScanner(response.Body) | 150 | scanner := bufio.NewScanner(body) |
147 | scanner.Split(bufio.ScanLines) | ||
148 | 151 | ||
149 | for scanner.Scan() { | 152 | for scanner.Scan() { |
150 | line := strings.Trim(scanner.Text(), "\r\n") | 153 | line := strings.Trim(scanner.Text(), "\r\n") |
@@ -380,25 +383,32 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
380 | } | 383 | } |
381 | 384 | ||
382 | if strings.HasPrefix(res.Header.Meta, "text/") { | 385 | if strings.HasPrefix(res.Header.Meta, "text/") { |
383 | // TODO: Handle encoding | 386 | buf := new(bytes.Buffer) |
384 | // https://stackoverflow.com/questions/32518432/how-to-convert-from-an-encoding-to-utf-8-in-go | 387 | |
388 | _, params, err := mime.ParseMediaType(res.Header.Meta) | ||
389 | if err != nil { | ||
390 | buf.ReadFrom(res.Body) | ||
391 | } else { | ||
392 | encoding, _ := charset.Lookup(params["charset"]) | ||
393 | readbuf := new(bytes.Buffer) | ||
394 | readbuf.ReadFrom(res.Body) | ||
395 | |||
396 | writer := transform.NewWriter(buf, encoding.NewDecoder()) | ||
397 | writer.Write(readbuf.Bytes()) | ||
398 | writer.Close() | ||
399 | } | ||
400 | |||
401 | var ( | ||
402 | rawText string | ||
403 | items []Item | ||
404 | ) | ||
385 | 405 | ||
386 | if strings.HasPrefix(res.Header.Meta, MIME_GEMINI) { | 406 | if strings.HasPrefix(res.Header.Meta, MIME_GEMINI) { |
387 | items := parseGeminiDocument(res, uri, hostport) | 407 | items = parseGeminiDocument(buf, uri, hostport) |
388 | tpl.Execute(w, struct { | 408 | } else { |
389 | Title string | 409 | rawText = buf.String() |
390 | URI string | ||
391 | Assets AssetList | ||
392 | RawText string | ||
393 | Lines []Item | ||
394 | Error bool | ||
395 | Protocol string | ||
396 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, "", items, false, "gemini"}) | ||
397 | return | ||
398 | } | 410 | } |
399 | 411 | ||
400 | buf := new(bytes.Buffer) | ||
401 | buf.ReadFrom(res.Body) | ||
402 | tpl.Execute(w, struct { | 412 | tpl.Execute(w, struct { |
403 | Title string | 413 | Title string |
404 | URI string | 414 | URI string |
@@ -407,7 +417,7 @@ func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, ass | |||
407 | Lines []Item | 417 | Lines []Item |
408 | Error bool | 418 | Error bool |
409 | Protocol string | 419 | Protocol string |
410 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, buf.String(), nil, false, "gemini"}) | 420 | }{uri, fmt.Sprintf("%s/%s", hostport, uri), assetList, rawText, items, false, "gemini"}) |
411 | } else { | 421 | } else { |
412 | io.Copy(w, res.Body) | 422 | io.Copy(w, res.Body) |
413 | } | 423 | } |
diff --git a/libgemini.go b/libgemini.go index 56e1463..20fc137 100644 --- a/libgemini.go +++ b/libgemini.go | |||
@@ -5,6 +5,7 @@ import ( | |||
5 | "crypto/tls" | 5 | "crypto/tls" |
6 | "errors" | 6 | "errors" |
7 | "io" | 7 | "io" |
8 | "mime" | ||
8 | "net/url" | 9 | "net/url" |
9 | "regexp" | 10 | "regexp" |
10 | "strconv" | 11 | "strconv" |
@@ -134,13 +135,14 @@ func ParseGeminiHeader(line string) (header *GeminiHeader, err error) { | |||
134 | meta := matches[2] | 135 | meta := matches[2] |
135 | 136 | ||
136 | if int(status/10) == 2 { | 137 | if int(status/10) == 2 { |
137 | if meta == "" { | 138 | mediaType, params, err := mime.ParseMediaType(meta) |
138 | meta = DEFAULT_MIME + ";charset=" + DEFAULT_CHARSET | ||
139 | } | ||
140 | 139 | ||
141 | mimeType := MimeTypePattern.FindString(meta) | 140 | if err != nil { |
142 | if strings.HasPrefix(mimeType, "text/") && MimeCharsetPattern.FindString(meta) == "" { | 141 | meta = DEFAULT_MIME + ";charset=" + DEFAULT_CHARSET |
143 | meta += ";charset=" + DEFAULT_CHARSET | 142 | } else if strings.HasPrefix(mediaType, "text/") { |
143 | if _, ok := params["charset"]; !ok { | ||
144 | meta += ";charset=" + DEFAULT_CHARSET | ||
145 | } | ||
144 | } | 146 | } |
145 | } | 147 | } |
146 | 148 | ||