2021-04-08 09:54:47 +02:00
|
|
|
package rest
|
|
|
|
|
|
|
|
import (
|
2021-04-11 13:03:41 +02:00
|
|
|
"encoding/json"
|
2022-05-03 11:34:25 +02:00
|
|
|
"golang.org/x/net/publicsuffix"
|
2021-04-08 09:54:47 +02:00
|
|
|
"net/http"
|
2021-04-11 09:50:27 +02:00
|
|
|
"net/url"
|
2021-04-19 20:22:38 +02:00
|
|
|
"strings"
|
2021-04-08 09:54:47 +02:00
|
|
|
)
|
|
|
|
|
2021-04-11 13:03:41 +02:00
|
|
|
// mimicing NotFound: https://golang.org/src/net/http/server.go?s=64787:64830#L2076
|
2021-04-08 09:54:47 +02:00
|
|
|
func BadRequest(w http.ResponseWriter) {
|
2021-04-11 15:42:44 +02:00
|
|
|
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TooManyRequests(w http.ResponseWriter) {
|
|
|
|
http.Error(w, http.StatusText(http.StatusTooManyRequests), http.StatusTooManyRequests)
|
2021-04-08 09:54:47 +02:00
|
|
|
}
|
|
|
|
|
2021-04-11 13:03:41 +02:00
|
|
|
func Unauthorized(w http.ResponseWriter) {
|
2021-04-11 15:42:44 +02:00
|
|
|
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
2021-04-11 13:03:41 +02:00
|
|
|
}
|
|
|
|
|
2021-04-19 20:22:38 +02:00
|
|
|
// Domain parses the target url to extract the domain as part of the allowed webmention targets.
|
|
|
|
// This is the same as conf.FetchDomain(wm.Target), only without config, and without error handling.
|
2021-05-02 11:40:45 +02:00
|
|
|
// Assumes http(s) protocol, which should have been validated before calling this.
|
2021-04-19 20:22:38 +02:00
|
|
|
func Domain(target string) string {
|
2022-05-03 11:34:25 +02:00
|
|
|
url, err := url.Parse(target)
|
|
|
|
if err != nil {
|
2021-05-02 11:40:45 +02:00
|
|
|
return target
|
|
|
|
}
|
2022-05-03 11:34:25 +02:00
|
|
|
host := url.Hostname()
|
|
|
|
if host == "" {
|
|
|
|
return target
|
|
|
|
}
|
|
|
|
|
|
|
|
suffix, _ := publicsuffix.PublicSuffix(host)
|
|
|
|
withPossibleSubdomain := strings.ReplaceAll(host, "."+suffix, "")
|
2021-05-02 11:40:45 +02:00
|
|
|
|
2021-04-19 20:22:38 +02:00
|
|
|
split := strings.Split(withPossibleSubdomain, ".")
|
2022-05-03 11:34:25 +02:00
|
|
|
if len(split) <= 1 {
|
|
|
|
return host
|
2021-04-19 20:22:38 +02:00
|
|
|
}
|
2022-05-03 11:34:25 +02:00
|
|
|
|
|
|
|
return strings.Join(split[1:], ".") + "." + suffix
|
2021-04-19 20:22:38 +02:00
|
|
|
}
|
|
|
|
|
2021-04-22 16:02:59 +02:00
|
|
|
type imageType []byte
|
|
|
|
|
|
|
|
var (
|
|
|
|
jpg = imageType{0xFF, 0xD8}
|
|
|
|
bmp = imageType{0x42, 0x4D}
|
|
|
|
gif = imageType{0x47, 0x49, 0x46}
|
|
|
|
png = imageType{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}
|
|
|
|
tiffI = imageType{0x49, 0x49, 0x2A, 0x00}
|
|
|
|
tiffM = imageType{0x4D, 0x4D, 0x00, 0x2A}
|
|
|
|
webp = imageType{0x52, 0x49, 0x46, 0x46} // RIFF 32 bits
|
|
|
|
supportedImageTypes = []imageType{jpg, png, gif, bmp, webp, tiffI, tiffM}
|
2021-05-02 09:41:13 +02:00
|
|
|
|
|
|
|
// SiloDomains are domains where mentions of multiple individuals may come from.
|
|
|
|
// These are privacy issues and will be anonymized as such.
|
2022-05-03 11:34:25 +02:00
|
|
|
SiloDomains = []string{
|
|
|
|
"brid.gy",
|
2022-06-22 21:19:44 +02:00
|
|
|
"brid-gy.appspot.com",
|
2022-05-03 11:34:25 +02:00
|
|
|
"twitter.com",
|
|
|
|
"facebook.com",
|
|
|
|
"indieweb.social",
|
|
|
|
"mastodon.social",
|
|
|
|
}
|
2021-04-22 16:02:59 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// IsRealImage checks the first few bytes of the provided data to see if it's a real image.
|
|
|
|
// Image headers supported: gif/jpg/png/webp/bmp
|
|
|
|
func IsRealImage(data []byte) bool {
|
|
|
|
if len(data) < 8 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, imgType := range supportedImageTypes {
|
|
|
|
checkedBits := 0
|
|
|
|
for i, bit := range imgType {
|
|
|
|
if data[i] == bit {
|
|
|
|
checkedBits++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if checkedBits == len(imgType) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2021-04-11 13:03:41 +02:00
|
|
|
func Json(w http.ResponseWriter, data interface{}) {
|
|
|
|
w.WriteHeader(200)
|
2021-04-11 13:11:41 +02:00
|
|
|
bytes, _ := json.MarshalIndent(data, "", " ")
|
2021-04-11 13:03:41 +02:00
|
|
|
w.Write(bytes)
|
|
|
|
}
|
|
|
|
|
2021-04-08 09:54:47 +02:00
|
|
|
func Accept(w http.ResponseWriter) {
|
|
|
|
w.WriteHeader(202)
|
2021-04-09 12:40:37 +02:00
|
|
|
w.Write([]byte("Thanks, bro. Will process this soon, pinky swear!"))
|
2021-04-08 09:54:47 +02:00
|
|
|
}
|
2021-04-11 09:50:27 +02:00
|
|
|
|
|
|
|
// assumes the URL is well-formed.
|
|
|
|
func BaseUrlOf(link string) *url.URL {
|
|
|
|
obj, _ := url.Parse(link)
|
|
|
|
baseUrl, _ := url.Parse(obj.Scheme + "://" + obj.Host)
|
|
|
|
return baseUrl
|
|
|
|
}
|