mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
phishing alert implementation
we now check when building the string through the `AttributedStringBuilder` if a URL is actually hiding a different link, if so, we create a custom URL that contains both the external and the internal URL to advise the user through an Alert about the risk
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// Copyright 2025 New Vector Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension CharacterSet {
|
||||
private static let urlAllowedSets: [CharacterSet] = [
|
||||
.urlUserAllowed,
|
||||
.urlPasswordAllowed,
|
||||
.urlHostAllowed,
|
||||
.urlPathAllowed,
|
||||
.urlQueryAllowed,
|
||||
.urlFragmentAllowed
|
||||
]
|
||||
|
||||
static let urlAllowedCharacters: CharacterSet = {
|
||||
// Start by including hash, which isn't in any URL set
|
||||
// Then include all URL-legal characters
|
||||
var result = CharacterSet(charactersIn: "#")
|
||||
for set in urlAllowedSets {
|
||||
result.formUnion(set)
|
||||
}
|
||||
return result
|
||||
}()
|
||||
|
||||
static let matrixUserIDAllowedCharacters = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyz0123456789._=-/@:")
|
||||
}
|
||||
@@ -101,6 +101,20 @@ extension URL: @retroactive ExpressibleByStringLiteral {
|
||||
return nil
|
||||
}
|
||||
|
||||
static let confirmationScheme = "confirm"
|
||||
|
||||
var requiresConfirmation: Bool {
|
||||
scheme == Self.confirmationScheme
|
||||
}
|
||||
|
||||
var confirmationParameters: ConfirmURLParameters? {
|
||||
guard requiresConfirmation,
|
||||
let queryItems = URLComponents(url: self, resolvingAgainstBaseURL: true)?.queryItems else {
|
||||
return nil
|
||||
}
|
||||
return ConfirmURLParameters(queryItems: queryItems)
|
||||
}
|
||||
|
||||
// MARK: Mocks
|
||||
|
||||
static var mockMXCAudio: URL { "mxc://matrix.org/1234567890AuDiO" }
|
||||
@@ -110,3 +124,25 @@ extension URL: @retroactive ExpressibleByStringLiteral {
|
||||
static var mockMXCAvatar: URL { "mxc://matrix.org/1234567890AvAtAr" }
|
||||
static var mockMXCUserAvatar: URL { "mxc://matrix.org/1234567890AvAtArUsEr" }
|
||||
}
|
||||
|
||||
struct ConfirmURLParameters {
|
||||
let internalURL: URL
|
||||
let linkString: String
|
||||
|
||||
var urlQueryItems: [URLQueryItem] {
|
||||
[URLQueryItem(name: "internalURL", value: internalURL.absoluteString),
|
||||
URLQueryItem(name: "linkString", value: linkString)]
|
||||
}
|
||||
}
|
||||
|
||||
extension ConfirmURLParameters {
|
||||
init?(queryItems: [URLQueryItem]) {
|
||||
guard let internalURLString = queryItems.first(where: { $0.name == "internalURL" })?.value,
|
||||
let internalURL = URL(string: internalURLString),
|
||||
let externalURLString = queryItems.first(where: { $0.name == "linkString" })?.value else {
|
||||
return nil
|
||||
}
|
||||
linkString = externalURLString
|
||||
self.internalURL = internalURL
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user