diff --git a/internal/reader/sanitizer/sanitizer.go b/internal/reader/sanitizer/sanitizer.go index 62d230c7..0551f0ee 100644 --- a/internal/reader/sanitizer/sanitizer.go +++ b/internal/reader/sanitizer/sanitizer.go @@ -138,46 +138,51 @@ var ( "linkedin.com/shareArticle", } - validURISchemes = map[string]struct{}{ - "apt": {}, - "bitcoin": {}, - "callto": {}, - "dav": {}, - "davs": {}, - "ed2k": {}, - "facetime": {}, - "feed": {}, - "ftp": {}, - "geo": {}, - "git": {}, - "gopher": {}, - "http": {}, - "https": {}, - "irc": {}, - "irc6": {}, - "ircs": {}, - "itms-apps": {}, - "itms": {}, - "magnet": {}, - "mailto": {}, - "news": {}, - "nntp": {}, - "rtmp": {}, - "sftp": {}, - "sip": {}, - "sips": {}, - "skype": {}, - "spotify": {}, - "ssh": {}, - "steam": {}, - "svn": {}, - "svn+ssh": {}, - "tel": {}, - "webcal": {}, - "xmpp": {}, + // See https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml + validURISchemes = []string{ + // Most commong schemes on top. + "https:", + "http:", + + // Then the rest. + "apt:", + "bitcoin:", + "callto:", + "dav:", + "davs:", + "ed2k:", + "facetime:", + "feed:", + "ftp:", + "geo:", + "git:", + "gopher:", + "irc:", + "irc6:", + "ircs:", + "itms-apps:", + "itms:", + "magnet:", + "mailto:", + "news:", + "nntp:", + "rtmp:", + "sftp:", + "sip:", + "sips:", + "skype:", + "spotify:", + "ssh:", + "steam:", + "svn:", + "svn+ssh:", + "tel:", + "webcal:", + "xmpp:", + // iOS Apps - "opener": {}, // https://www.opener.link - "hack": {}, // https://apps.apple.com/it/app/hack-for-hacker-news-reader/id1464477788?l=en-GB + "opener:", // https://www.opener.link + "hack:", // https://apps.apple.com/it/app/hack-for-hacker-news-reader/id1464477788?l=en-GB } dataAttributeAllowedPrefixes = []string{ @@ -467,23 +472,22 @@ func hasRequiredAttributes(tagName string, attributes []string) bool { } } -// See https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml func hasValidURIScheme(absoluteURL string) bool { - colonIndex := strings.IndexByte(absoluteURL, ':') - // Scheme must exist (colonIndex > 0). An empty scheme (e.g. ":foo") is not allowed. - if colonIndex <= 0 { - return false + for _, scheme := range validURISchemes { + if strings.HasPrefix(absoluteURL, scheme) { + return true + } } - - scheme := absoluteURL[:colonIndex] - _, ok := validURISchemes[strings.ToLower(scheme)] - return ok + return false } func isBlockedResource(absoluteURL string) bool { - return slices.ContainsFunc(blockedResourceURLSubstrings, func(element string) bool { - return strings.Contains(absoluteURL, element) - }) + for _, blockedURL := range blockedResourceURLSubstrings { + if strings.Contains(absoluteURL, blockedURL) { + return true + } + } + return false } func isValidIframeSource(iframeSourceURL string) bool { diff --git a/miniflux.1 b/miniflux.1 index fe059cf7..b0ba0bbf 100644 --- a/miniflux.1 +++ b/miniflux.1 @@ -1,5 +1,5 @@ .\" Manpage for miniflux. -.TH "MINIFLUX" "1" "August 19, 2025" "\ \&" "\ \&" +.TH "MINIFLUX" "1" "September 29, 2025" "\ \&" "\ \&" .SH NAME miniflux \- Minimalist and opinionated feed reader @@ -486,7 +486,9 @@ Set to 1 to authorize OAuth2 user creation\&. Disabled by default\&. .TP .B POLLING_FREQUENCY -Refresh interval in minutes for feeds\&. +Interval for the background job scheduler. +.br +Determines how often a batch of feeds is selected for refresh, based on their last refresh time\&. .br Default is 60 minutes\&. .TP