plugins/viewhtml: add image proxy

This commit is contained in:
Simon Ser 2020-02-25 15:45:43 +01:00
parent 8c4fd20e27
commit a8a3c82579
No known key found for this signature in database
GPG key ID: 0FDE7BE0E88F5E48
2 changed files with 72 additions and 8 deletions

View file

@ -1,10 +1,59 @@
package koushinviewhtml
import (
"io"
"mime"
"net/http"
"net/url"
"strconv"
"strings"
"git.sr.ht/~emersion/koushin"
"github.com/labstack/echo/v4"
)
var (
proxyEnabled = true
proxyMaxSize = 5 * 1024 * 1024 // 5 MiB
)
func init() {
p := koushin.GoPlugin{Name: "viewhtml"}
p.GET("/proxy", func(ctx *koushin.Context) error {
if !proxyEnabled {
return echo.NewHTTPError(http.StatusForbidden, "proxy disabled")
}
u, err := url.Parse(ctx.QueryParam("src"))
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "invalid URL")
}
if u.Scheme != "https" {
return echo.NewHTTPError(http.StatusBadRequest, "invalid scheme")
}
resp, err := http.Get(u.String())
if err != nil {
return err
}
defer resp.Body.Close()
mediaType, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
if err != nil || !strings.HasPrefix(mediaType, "image/") {
return echo.NewHTTPError(http.StatusBadRequest, "invalid resource type")
}
size, err := strconv.Atoi(resp.Header.Get("Content-Length"))
if err != nil || size > proxyMaxSize {
return echo.NewHTTPError(http.StatusBadRequest, "invalid resource length")
}
ctx.Response().Header().Set("Content-Length", strconv.Itoa(size))
lr := io.LimitedReader{resp.Body, int64(proxyMaxSize)}
return ctx.Stream(http.StatusOK, mediaType, &lr)
})
koushin.RegisterPluginLoader(p.Loader())
}

View file

@ -80,17 +80,32 @@ func (san *sanitizer) sanitizeImageURL(src string) string {
return "about:blank"
}
switch strings.ToLower(u.Scheme) {
// TODO: mid support?
if !strings.EqualFold(u.Scheme, "cid") || san.msg == nil {
case "cid":
if san.msg == nil {
return "about:blank"
}
part := san.msg.PartByID(u.Opaque)
if part == nil || !strings.HasPrefix(part.MIMEType, "image/") {
return "about:blank"
}
return part.URL(true).String()
case "https":
if !proxyEnabled {
return "about:blank"
}
proxyURL := url.URL{Path: "/proxy"}
proxyQuery := make(url.Values)
proxyQuery.Set("src", u.String())
proxyURL.RawQuery = proxyQuery.Encode()
return proxyURL.String()
default:
return "about:blank"
}
part := san.msg.PartByID(u.Opaque)
if part == nil || !strings.HasPrefix(part.MIMEType, "image/") {
return "about:blank"
}
return part.URL(true).String()
}
func (san *sanitizer) sanitizeCSSDecls(decls []*css.Declaration) []*css.Declaration {