From cdfc220d5df547bc4fbe3157ddfa22c614eb737c Mon Sep 17 00:00:00 2001 From: Rasmus Dahlberg Date: Thu, 23 Mar 2023 19:33:21 +0100 Subject: Add onion location parsing --- internal/onionloc/onionloc.go | 74 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 internal/onionloc/onionloc.go (limited to 'internal/onionloc/onionloc.go') diff --git a/internal/onionloc/onionloc.go b/internal/onionloc/onionloc.go new file mode 100644 index 0000000..63e512a --- /dev/null +++ b/internal/onionloc/onionloc.go @@ -0,0 +1,74 @@ +package onionloc + +import ( + "net/http" + "strings" + + "golang.org/x/net/html" +) + +const ( + HTTPHeaderName = "Onion-Location" +) + +func HTTP(rsp *http.Response) (string, bool) { + v, ok := rsp.Header[HTTPHeaderName] + if !ok { + return "", false + } + if len(v) != 1 { + return "", false + } + return v[0], true +} + +func HTML(rsp *http.Response) (string, bool) { + z := html.NewTokenizer(rsp.Body) + for { + tt := z.Next() + if tt == html.ErrorToken { + return "", false // EOF and other errors + } + + switch tt { + case html.StartTagToken, html.SelfClosingTagToken: + t := z.Token() + + // Looking for the html meta tag, see: + // https://www.w3schools.com/tags/tag_meta.asp + // + // We expect two attributes: "key" and "content" + if strings.ToLower(t.Data) != "meta" { + break + } + if len(t.Attr) != 2 { + break + } + + // We're looking for the "http-equiv" key, see: + // https://www.w3schools.com/tags/att_meta_http_equiv.asp + // + // In particular with the value "onion-location", see: + // https://community.torproject.org/onion-services/advanced/onion-location/ + // + // If we have all this and a following content + // attribute, that is the Onion-Location URL that this + // page advertises. We make no attempt to validate + // whether the content value is really an onion address. + attr := t.Attr[0] + if strings.ToLower(attr.Key) != "http-equiv" { + break + } + if strings.ToLower(attr.Val) != "onion-location" { + break + } + attr = t.Attr[1] + if strings.ToLower(attr.Key) != "content" { + break + } + + return attr.Val, true + default: + } + } +} -- cgit v1.2.3