diff options
| -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 | ||
