From 38485ede265d22e11a316b4d66de1bf0feb945be Mon Sep 17 00:00:00 2001 From: Volpeon Date: Sat, 24 Jul 2021 09:46:59 +0200 Subject: Update --- internal/port/gemini.go | 292 ------------------------------------------------ 1 file changed, 292 deletions(-) delete mode 100644 internal/port/gemini.go (limited to 'internal/port/gemini.go') diff --git a/internal/port/gemini.go b/internal/port/gemini.go deleted file mode 100644 index f574816..0000000 --- a/internal/port/gemini.go +++ /dev/null @@ -1,292 +0,0 @@ -package port - -import ( - "bytes" - "fmt" - "html/template" - "io" - "log" - "mime" - "net/http" - "net/url" - "strings" - - "golang.org/x/net/html/charset" - "golang.org/x/text/transform" - - "git.vulpes.one/Feuerfuchs/port/pkg/libgemini" - - "github.com/temoto/robotstxt" -) - -type GeminiTemplateVariables struct { - Title string - URL string - Assets AssetList - Sections []GeminiSection - Nav []GeminiNavItem - IsPlain bool -} - -type GeminiNavItem struct { - Label string - URL string - Current bool -} - -type GeminiSection struct { - Type string - Text string - URL template.URL - Items []string -} - -func urlToGeminiNav(url string) (items []GeminiNavItem) { - partialURL := "/gemini" - parts := strings.Split(url, "/") - - if len(parts) != 0 && parts[len(parts)-1] == "" { - parts = parts[:len(parts)-1] - } - - for _, part := range parts { - partialURL = partialURL + "/" + part - - items = append(items, GeminiNavItem{ - Label: part, - URL: partialURL, - Current: false, - }) - } - - items[len(items)-1].Current = true - - return -} - -func resolveURL(uri string, baseURL *url.URL) (resolvedURL string) { - if strings.HasPrefix(uri, "//") { - resolvedURL = "/gemini/" + strings.TrimPrefix(uri, "//") - } else if strings.HasPrefix(uri, "gemini://") { - resolvedURL = "/gemini/" + strings.TrimPrefix(uri, "gemini://") - } else if strings.HasPrefix(uri, "gopher://") { - resolvedURL = "/gopher/" + strings.TrimPrefix(uri, "gopher://") - } else { - url, err := url.Parse(uri) - if err != nil { - return "" - } - adjustedURL := baseURL.ResolveReference(url) - path := adjustedURL.Path - if !strings.HasPrefix(path, "/") { - path = "/" + path - } - if adjustedURL.Scheme == "gemini" { - resolvedURL = "/gemini/" + adjustedURL.Host + path - } else if adjustedURL.Scheme == "gopher" { - resolvedURL = "/gopher/" + adjustedURL.Host + path - } else { - resolvedURL = adjustedURL.String() - } - } - - return -} - -func parseGeminiDocument(body *bytes.Buffer, uri string, hostport string) (sections []GeminiSection) { - baseURL, err := url.Parse(fmt.Sprintf( - "gemini://%s/%s", - hostport, - uri, - )) - if err != nil { - return - } - - unpreppedSections := libgemini.ParseGeminiDocument(body) - - for _, section := range unpreppedSections { - if section.Type != libgemini.LINK { - sections = append(sections, GeminiSection{ - Type: section.Type.String(), - Text: section.Text, - URL: template.URL(section.URL), - Items: section.Items, - }) - } else { - sections = append(sections, GeminiSection{ - Type: section.Type.String(), - Text: section.Text, - URL: template.URL(resolveURL(section.URL, baseURL)), - Items: section.Items, - }) - } - } - - return -} - -func GeminiHandler(tpl *template.Template, robotsdata *robotstxt.RobotsData, assetList AssetList, robotsdebug bool) http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - agent := req.UserAgent() - path := strings.TrimPrefix(req.URL.Path, "/gemini/") - - if robotsdata != nil && robotsdebug && !robotsdata.TestAgent(path, agent) { - log.Printf("UserAgent %s ignored robots.txt", agent) - } - - parts := strings.Split(path, "/") - hostport := parts[0] - - if len(hostport) == 0 { - http.Redirect(w, req, "/", http.StatusFound) - return - } - - title := hostport - - var qs string - - if req.URL.RawQuery != "" { - qs = fmt.Sprintf("?%s", url.QueryEscape(req.URL.RawQuery)) - } - - uri, err := url.QueryUnescape(strings.Join(parts[1:], "/")) - if err != nil { - if e := tpl.Execute(w, GeminiTemplateVariables{ - Title: title, - URL: hostport, - Assets: assetList, - Sections: []GeminiSection{{ - Type: libgemini.RAW_TEXT.String(), - Text: fmt.Sprintf("Error: %s", err), - }}, - Nav: urlToGeminiNav(hostport), - IsPlain: true, - }); e != nil { - log.Println("Template error: " + e.Error()) - log.Println(err.Error()) - } - return - } - - if uri != "" { - title = fmt.Sprintf("%s/%s", hostport, uri) - } - - res, err := libgemini.Get( - fmt.Sprintf( - "gemini://%s/%s%s", - hostport, - uri, - qs, - ), - ) - - if err != nil { - if e := tpl.Execute(w, GeminiTemplateVariables{ - Title: title, - URL: fmt.Sprintf("%s/%s", hostport, uri), - Assets: assetList, - Sections: []GeminiSection{{ - Type: libgemini.RAW_TEXT.String(), - Text: fmt.Sprintf("Error: %s", err), - }}, - Nav: urlToGeminiNav(fmt.Sprintf("%s/%s", hostport, uri)), - IsPlain: true, - }); e != nil { - log.Println("Template error: " + e.Error()) - log.Println(err.Error()) - } - return - } - - if int(res.Header.Status/10) == 3 { - baseURL, err := url.Parse(fmt.Sprintf( - "gemini://%s/%s", - hostport, - uri, - )) - if err != nil { - if e := tpl.Execute(w, GeminiTemplateVariables{ - Title: title, - URL: fmt.Sprintf("%s/%s", hostport, uri), - Assets: assetList, - Sections: []GeminiSection{{ - Type: libgemini.RAW_TEXT.String(), - Text: fmt.Sprintf("Error: %s", err), - }}, - Nav: urlToGeminiNav(fmt.Sprintf("%s/%s", hostport, uri)), - IsPlain: true, - }); e != nil { - log.Println("Template error: " + e.Error()) - log.Println(err.Error()) - } - return - } - - http.Redirect(w, req, resolveURL(res.Header.Meta, baseURL), http.StatusFound) - return - } - - if int(res.Header.Status/10) != 2 { - if err := tpl.Execute(w, GeminiTemplateVariables{ - Title: title, - URL: fmt.Sprintf("%s/%s", hostport, uri), - Assets: assetList, - Sections: []GeminiSection{{ - Type: libgemini.RAW_TEXT.String(), - Text: fmt.Sprintf("Error %d: %s", res.Header.Status, res.Header.Meta), - }}, - Nav: urlToGeminiNav(fmt.Sprintf("%s/%s", hostport, uri)), - IsPlain: true, - }); err != nil { - log.Println("Template error: " + err.Error()) - } - return - } - - if strings.HasPrefix(res.Header.Meta, "text/") && !strings.HasPrefix(res.Header.Meta, "text/html") && !strings.HasPrefix(res.Header.Meta, "text/css") { - buf := new(bytes.Buffer) - - _, params, err := mime.ParseMediaType(res.Header.Meta) - if err != nil { - buf.ReadFrom(res.Body) - } else { - encoding, _ := charset.Lookup(params["charset"]) - readbuf := new(bytes.Buffer) - readbuf.ReadFrom(res.Body) - - writer := transform.NewWriter(buf, encoding.NewDecoder()) - writer.Write(readbuf.Bytes()) - writer.Close() - } - - var sections []GeminiSection - isPlain := true - - if strings.HasPrefix(res.Header.Meta, libgemini.MIME_GEMINI) { - sections = parseGeminiDocument(buf, uri, hostport) - isPlain = false - } else { - sections = append(sections, GeminiSection{ - Type: libgemini.RAW_TEXT.String(), - Text: buf.String(), - }) - } - - if err := tpl.Execute(w, GeminiTemplateVariables{ - Title: title, - URL: fmt.Sprintf("%s/%s", hostport, uri), - Assets: assetList, - Sections: sections, - Nav: urlToGeminiNav(fmt.Sprintf("%s/%s", hostport, uri)), - IsPlain: isPlain, - }); err != nil { - log.Println("Template error: " + err.Error()) - } - } else { - io.Copy(w, res.Body) - } - } -} -- cgit v1.2.3-70-g09d2