From 4ddb6c8d4f29729898638d74e54a64d4c388e43b Mon Sep 17 00:00:00 2001 From: Nate Weaver Date: Tue, 7 Apr 2020 16:04:50 -0500 Subject: [PATCH] Only allow certain inline tags to remain in the title; HTML-encode the rest --- Frameworks/Articles/Article.swift | 35 +++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Frameworks/Articles/Article.swift b/Frameworks/Articles/Article.swift index 6e13633cc..c97f94731 100644 --- a/Frameworks/Articles/Article.swift +++ b/Frameworks/Articles/Article.swift @@ -86,3 +86,38 @@ public extension Array where Element == Article { return map { $0.articleID } } } + +public extension Article { + static let allowedTags: Set = ["b", "bdi", "bdo", "cite", "code", "del", "dfn", "em", "i", "ins", "kbd", "mark", "q", "rb", "rp", "rt", "rtc", "ruby", "s", "samp", "small", "strong", "sub", "sup", "time", "u", "var"] + + func sanitizedTitle(forHTML: Bool = true) -> String? { + guard let title = title else { return nil } + + let scanner = Scanner(string: title) + scanner.charactersToBeSkipped = nil + var result = "" + result.reserveCapacity(title.count) + + while !scanner.isAtEnd { + if let text = scanner.scanUpToString("<") { + result.append(text) + } + + if let _ = scanner.scanString("<") { + // All the allowed tags currently don't allow attributes + if let tag = scanner.scanUpToString(">") { + if Self.allowedTags.contains(tag.replacingOccurrences(of: "/", with: "")) { + forHTML ? result.append("<\(tag)>") : result.append("") + } else { + forHTML ? result.append("<\(tag)>") : result.append("<\(tag)>") + } + + let _ = scanner.scanString(">") + } + } + } + + return result + } + +}