- models.AllowedFrontendURL: empty, or an absolute http(s) URL with a host and without whitespace, control characters, a double quote, <, > or & - classes.Rewrite leaves the document unchanged for a refused value, inserts through EscapeText/EscapeAttr and keeps a loc or href that would not stay an http(s) URL - TestRewriteUnsafeFrontendURL, TestAllowedFrontendURL and a stored-row check in TestSitemapImportSmoke
70 lines
2.5 KiB
Go
70 lines
2.5 KiB
Go
package classes
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
|
|
"git.golem15.com/golem15/sm-sitemap-plugin/models"
|
|
)
|
|
|
|
// The PHP routes.php patterns of the frontend rewrite.
|
|
var (
|
|
locElement = regexp.MustCompile(`<loc>(.*?)</loc>`)
|
|
xhtmlLinkRef = regexp.MustCompile(`(<xhtml:link[^>]*href=")([^"]*)(")`)
|
|
)
|
|
|
|
// Rewrite is the frontend_url rewrite of PHP routes.php: with frontendURL
|
|
// set, backendURL is replaced literally (str_replace) inside every loc
|
|
// element, inside every xhtml:link href and in the exact stylesheet href.
|
|
// Both URLs are right-trimmed of slashes first. An empty frontendURL (or
|
|
// "0", which PHP reads as false) leaves xml unchanged.
|
|
//
|
|
// PHP inserted the stored text as it was. Three rules keep that text out of
|
|
// the document unless it is a plain http(s) URL (T-17-15):
|
|
//
|
|
// - a frontendURL that models.AllowedFrontendURL refuses leaves xml
|
|
// unchanged, whatever is stored in the settings row;
|
|
// - the frontend URL is inserted through EscapeText in loc and through
|
|
// EscapeAttr in the hrefs. Both are the identity for every accepted
|
|
// value, which keeps the PHP bytes;
|
|
// - a loc or xhtml:link href whose rewritten value does not start with
|
|
// http:// or https:// keeps its value. The generator applies the same
|
|
// filter before the rewrite.
|
|
func Rewrite(xml, backendURL, frontendURL string) string {
|
|
if frontendURL == "" || frontendURL == "0" {
|
|
return xml
|
|
}
|
|
if !models.AllowedFrontendURL(frontendURL) {
|
|
return xml
|
|
}
|
|
frontend := strings.TrimRight(frontendURL, "/")
|
|
backend := strings.TrimRight(backendURL, "/")
|
|
if backend == "" {
|
|
return xml
|
|
}
|
|
frontendText, frontendAttr := EscapeText(frontend), EscapeAttr(frontend)
|
|
xml = locElement.ReplaceAllStringFunc(xml, func(m string) string {
|
|
inner := m[len("<loc>") : len(m)-len("</loc>")]
|
|
rewritten := strings.ReplaceAll(inner, backend, frontendText)
|
|
if !httpURL(rewritten) {
|
|
return m
|
|
}
|
|
return "<loc>" + rewritten + "</loc>"
|
|
})
|
|
xml = xhtmlLinkRef.ReplaceAllStringFunc(xml, func(m string) string {
|
|
sub := xhtmlLinkRef.FindStringSubmatch(m)
|
|
rewritten := strings.ReplaceAll(sub[2], backend, frontendAttr)
|
|
if !httpURL(rewritten) {
|
|
return m
|
|
}
|
|
return sub[1] + rewritten + sub[3]
|
|
})
|
|
return strings.ReplaceAll(xml, `href="`+backend+`/sitemap.xsl"`, `href="`+frontendAttr+`/sitemap.xsl"`)
|
|
}
|
|
|
|
// BackendURL is PHP rtrim(url('/'), '/') for a request whose root URL is
|
|
// root: the URL the rewrite replaces.
|
|
func BackendURL(root string) string {
|
|
return strings.TrimRight(URLTo(root, "/"), "/")
|
|
}
|