2017-11-20 13:16:06 -08:00
|
|
|
//
|
|
|
|
// FaviconURLFinder.swift
|
2018-08-28 22:18:24 -07:00
|
|
|
// NetNewsWire
|
2017-11-20 13:16:06 -08:00
|
|
|
//
|
|
|
|
// Created by Brent Simmons on 11/20/17.
|
|
|
|
// Copyright © 2017 Ranchero Software. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
import Foundation
|
2020-02-01 01:09:36 -06:00
|
|
|
import CoreServices
|
2017-11-20 13:16:06 -08:00
|
|
|
import RSParser
|
2024-02-24 20:39:44 -08:00
|
|
|
import UniformTypeIdentifiers
|
2017-11-20 13:16:06 -08:00
|
|
|
|
2019-11-25 19:54:09 -06:00
|
|
|
// The favicon URLs may be specified in the head section of the home page.
|
2017-11-20 13:16:06 -08:00
|
|
|
|
|
|
|
struct FaviconURLFinder {
|
|
|
|
|
2020-01-31 16:33:35 -06:00
|
|
|
/// Uniform types to ignore when finding favicon URLs.
|
2024-02-24 20:39:44 -08:00
|
|
|
static var ignoredTypes = [UTType.svg]
|
2020-01-31 16:09:01 -06:00
|
|
|
|
|
|
|
/// Finds favicon URLs in a web page.
|
|
|
|
/// - Parameters:
|
|
|
|
/// - homePageURL: The page to search.
|
|
|
|
/// - completion: A closure called when the links have been found.
|
|
|
|
/// - urls: An array of favicon URLs as strings.
|
2020-02-01 19:19:33 -06:00
|
|
|
static func findFaviconURLs(with homePageURL: String, _ completion: @escaping (_ urls: [String]?) -> Void) {
|
2020-01-31 16:09:01 -06:00
|
|
|
|
2021-07-18 17:01:59 -05:00
|
|
|
guard let _ = URL(unicodeString: homePageURL) else {
|
2020-01-31 16:09:01 -06:00
|
|
|
completion(nil)
|
|
|
|
return
|
|
|
|
}
|
2020-01-31 15:59:16 -06:00
|
|
|
|
|
|
|
// If the favicon has an explicit type, check that for an ignored type; otherwise, check the file extension.
|
2024-02-24 20:39:44 -08:00
|
|
|
HTMLMetadataDownloader.downloadMetadata(for: homePageURL) { htmlMetadata in
|
|
|
|
let faviconURLs = htmlMetadata?.favicons.compactMap { favicon -> String? in
|
2020-01-31 15:59:16 -06:00
|
|
|
|
2024-02-24 20:39:44 -08:00
|
|
|
guard shouldAllowFavicon(favicon) else {
|
|
|
|
return nil
|
|
|
|
}
|
2020-02-08 17:46:48 -06:00
|
|
|
return favicon.urlString
|
2024-02-24 20:39:44 -08:00
|
|
|
}
|
2020-01-31 15:59:16 -06:00
|
|
|
|
|
|
|
completion(faviconURLs)
|
2017-12-13 19:46:03 -08:00
|
|
|
}
|
2017-11-20 13:16:06 -08:00
|
|
|
}
|
2024-02-24 20:39:44 -08:00
|
|
|
|
|
|
|
static func shouldAllowFavicon(_ favicon: RSHTMLMetadataFavicon) -> Bool {
|
|
|
|
|
|
|
|
// Check mime type.
|
|
|
|
if let mimeType = favicon.type, let utType = UTType(mimeType: mimeType) {
|
|
|
|
if ignoredTypes.contains(utType) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check file extension.
|
|
|
|
if let urlString = favicon.urlString, let url = URL(string: urlString), let utType = UTType(filenameExtension: url.pathExtension) {
|
|
|
|
if ignoredTypes.contains(utType) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
2017-11-20 13:16:06 -08:00
|
|
|
}
|
|
|
|
|