mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-05 19:28:46 +02:00
Various fixes
This commit is contained in:
parent
adc0d5ba6e
commit
c4e1049396
5 changed files with 113 additions and 28 deletions
|
|
@ -67,6 +67,8 @@ public final class ChatMessageItemAssociatedData: Equatable {
|
|||
public let isSuspiciousPeer: Bool
|
||||
public let showTextAsPlaceholder: Bool
|
||||
public let accountCountry: String?
|
||||
public let isParticipant: Bool
|
||||
public let invitedOn: Int32?
|
||||
|
||||
public init(
|
||||
automaticDownloadPeerType: MediaAutoDownloadPeerType,
|
||||
|
|
@ -104,7 +106,9 @@ public final class ChatMessageItemAssociatedData: Equatable {
|
|||
showSensitiveContent: Bool = false,
|
||||
isSuspiciousPeer: Bool = false,
|
||||
showTextAsPlaceholder: Bool = false,
|
||||
accountCountry: String? = nil
|
||||
accountCountry: String? = nil,
|
||||
isParticipant: Bool = false,
|
||||
invitedOn: Int32? = nil
|
||||
) {
|
||||
self.automaticDownloadPeerType = automaticDownloadPeerType
|
||||
self.automaticDownloadPeerId = automaticDownloadPeerId
|
||||
|
|
@ -142,6 +146,8 @@ public final class ChatMessageItemAssociatedData: Equatable {
|
|||
self.isSuspiciousPeer = isSuspiciousPeer
|
||||
self.showTextAsPlaceholder = showTextAsPlaceholder
|
||||
self.accountCountry = accountCountry
|
||||
self.isParticipant = isParticipant
|
||||
self.invitedOn = invitedOn
|
||||
}
|
||||
|
||||
public static func == (lhs: ChatMessageItemAssociatedData, rhs: ChatMessageItemAssociatedData) -> Bool {
|
||||
|
|
@ -241,6 +247,12 @@ public final class ChatMessageItemAssociatedData: Equatable {
|
|||
if lhs.accountCountry != rhs.accountCountry {
|
||||
return false
|
||||
}
|
||||
if lhs.isParticipant != rhs.isParticipant {
|
||||
return false
|
||||
}
|
||||
if lhs.invitedOn != rhs.invitedOn {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2690,6 +2690,14 @@ public class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
|||
if !poll.countries.isEmpty, let accountCountry = item.associatedData.accountCountry, !poll.countries.contains(accountCountry) {
|
||||
isRestricted = true
|
||||
}
|
||||
if poll.restrictToSubscribers {
|
||||
let period: Int32 = item.context.account.testingEnvironment ? 5 * 60 : 24 * 60 * 60
|
||||
if !item.associatedData.isParticipant {
|
||||
isRestricted = true
|
||||
} else if let invitedOn = item.associatedData.invitedOn, invitedOn + period > Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) {
|
||||
isRestricted = true
|
||||
}
|
||||
}
|
||||
|
||||
orderedPollOptions = resolvedOptionOrder(for: item)
|
||||
|
||||
|
|
|
|||
|
|
@ -373,6 +373,8 @@ private func extractAssociatedData(
|
|||
var automaticMediaDownloadPeerType: MediaAutoDownloadPeerType = .channel
|
||||
var contactsPeerIds: Set<PeerId> = Set()
|
||||
var channelDiscussionGroup: ChatMessageItemAssociatedData.ChannelDiscussionGroupStatus = .unknown
|
||||
var isParticipant = false
|
||||
var invitedOn: Int32?
|
||||
if case let .peer(peerId) = chatLocation {
|
||||
automaticDownloadPeerId = peerId
|
||||
|
||||
|
|
@ -396,11 +398,15 @@ private func extractAssociatedData(
|
|||
} else if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
for entry in view.additionalData {
|
||||
if case let .peer(_, value) = entry {
|
||||
if let channel = value as? TelegramChannel, case .group = channel.info {
|
||||
automaticMediaDownloadPeerType = .group
|
||||
if let channel = value as? TelegramChannel {
|
||||
if case .group = channel.info {
|
||||
automaticMediaDownloadPeerType = .group
|
||||
}
|
||||
isParticipant = channel.participationStatus == .member
|
||||
}
|
||||
} else if case let .cachedPeerData(dataPeerId, cachedData) = entry, dataPeerId == peerId {
|
||||
if let cachedData = cachedData as? CachedChannelData {
|
||||
invitedOn = cachedData.invitedOn
|
||||
switch cachedData.linkedDiscussionPeerId {
|
||||
case let .known(value):
|
||||
channelDiscussionGroup = .known(value)
|
||||
|
|
@ -422,7 +428,7 @@ private func extractAssociatedData(
|
|||
automaticDownloadPeerId = message.peerId
|
||||
}
|
||||
|
||||
return ChatMessageItemAssociatedData(automaticDownloadPeerType: automaticMediaDownloadPeerType, automaticDownloadPeerId: automaticDownloadPeerId, automaticDownloadNetworkType: automaticDownloadNetworkType, preferredStoryHighQuality: preferredStoryHighQuality, isRecentActions: false, subject: subject, contactsPeerIds: contactsPeerIds, channelDiscussionGroup: channelDiscussionGroup, animatedEmojiStickers: animatedEmojiStickers, additionalAnimatedEmojiStickers: additionalAnimatedEmojiStickers, currentlyPlayingMessageId: currentlyPlayingMessageId, isCopyProtectionEnabled: isCopyProtectionEnabled, availableReactions: availableReactions, availableMessageEffects: availableMessageEffects, savedMessageTags: savedMessageTags, defaultReaction: defaultReaction, areStarReactionsEnabled: areStarReactionsEnabled, isPremium: isPremium, accountPeer: accountPeer, alwaysDisplayTranscribeButton: alwaysDisplayTranscribeButton, topicAuthorId: topicAuthorId, hasBots: hasBots, translateToLanguage: translateToLanguage, maxReadStoryId: maxReadStoryId, recommendedChannels: recommendedChannels, audioTranscriptionTrial: audioTranscriptionTrial, chatThemes: chatThemes, deviceContactsNumbers: deviceContactsNumbers, isInline: isInline, showSensitiveContent: showSensitiveContent, isSuspiciousPeer: isSuspiciousPeer, accountCountry: accountCountry)
|
||||
return ChatMessageItemAssociatedData(automaticDownloadPeerType: automaticMediaDownloadPeerType, automaticDownloadPeerId: automaticDownloadPeerId, automaticDownloadNetworkType: automaticDownloadNetworkType, preferredStoryHighQuality: preferredStoryHighQuality, isRecentActions: false, subject: subject, contactsPeerIds: contactsPeerIds, channelDiscussionGroup: channelDiscussionGroup, animatedEmojiStickers: animatedEmojiStickers, additionalAnimatedEmojiStickers: additionalAnimatedEmojiStickers, currentlyPlayingMessageId: currentlyPlayingMessageId, isCopyProtectionEnabled: isCopyProtectionEnabled, availableReactions: availableReactions, availableMessageEffects: availableMessageEffects, savedMessageTags: savedMessageTags, defaultReaction: defaultReaction, areStarReactionsEnabled: areStarReactionsEnabled, isPremium: isPremium, accountPeer: accountPeer, alwaysDisplayTranscribeButton: alwaysDisplayTranscribeButton, topicAuthorId: topicAuthorId, hasBots: hasBots, translateToLanguage: translateToLanguage, maxReadStoryId: maxReadStoryId, recommendedChannels: recommendedChannels, audioTranscriptionTrial: audioTranscriptionTrial, chatThemes: chatThemes, deviceContactsNumbers: deviceContactsNumbers, isInline: isInline, showSensitiveContent: showSensitiveContent, isSuspiciousPeer: isSuspiciousPeer, accountCountry: accountCountry, isParticipant: isParticipant, invitedOn: invitedOn)
|
||||
}
|
||||
|
||||
private extension ChatHistoryLocationInput {
|
||||
|
|
|
|||
|
|
@ -516,6 +516,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||
return
|
||||
}
|
||||
#endif*/
|
||||
self.webView?.bindTrustedOrigin(from: url)
|
||||
self.webView?.load(URLRequest(url: url))
|
||||
}
|
||||
|
||||
|
|
@ -1092,7 +1093,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||
guard let controller = self.controller else {
|
||||
return
|
||||
}
|
||||
guard message.frameInfo.isMainFrame else {
|
||||
guard self.webView?.isTrustedMainFrameMessage(message) == true else {
|
||||
return
|
||||
}
|
||||
guard let body = message.body as? [String: Any] else {
|
||||
|
|
|
|||
|
|
@ -36,11 +36,27 @@ private class WebViewTouchGestureRecognizer: UITapGestureRecognizer {
|
|||
}
|
||||
}
|
||||
|
||||
private let eventProxySource = "var TelegramWebviewProxyProto = function() {}; " +
|
||||
"TelegramWebviewProxyProto.prototype.postEvent = function(eventName, eventData) { " +
|
||||
"window.webkit.messageHandlers.performAction.postMessage({'eventName': eventName, 'eventData': eventData}); " +
|
||||
"}; " +
|
||||
"var TelegramWebviewProxy = new TelegramWebviewProxyProto();"
|
||||
private func jsStringLiteral(_ value: String) -> String {
|
||||
if let data = try? JSONSerialization.data(withJSONObject: [value], options: []), let string = String(data: data, encoding: .utf8), string.hasPrefix("["), string.hasSuffix("]") {
|
||||
return String(string.dropFirst().dropLast())
|
||||
}
|
||||
return "\"\""
|
||||
}
|
||||
|
||||
private func eventProxySource(trustedOrigin: String) -> String {
|
||||
return """
|
||||
(function() {
|
||||
if (window.location.origin !== \(jsStringLiteral(trustedOrigin))) {
|
||||
return;
|
||||
}
|
||||
var TelegramWebviewProxyProto = function() {};
|
||||
TelegramWebviewProxyProto.prototype.postEvent = function(eventName, eventData) {
|
||||
window.webkit.messageHandlers.performAction.postMessage({'eventName': eventName, 'eventData': eventData});
|
||||
};
|
||||
window.TelegramWebviewProxy = new TelegramWebviewProxyProto();
|
||||
})();
|
||||
"""
|
||||
}
|
||||
|
||||
private let selectionSource = "var css = '*{-webkit-touch-callout:none;} :not(input):not(textarea):not([\"contenteditable\"=\"true\"]){-webkit-user-select:none;}';"
|
||||
+ " var head = document.head || document.getElementsByTagName('head')[0];"
|
||||
|
|
@ -91,6 +107,7 @@ function tgBrowserDisconnectObserver() {
|
|||
|
||||
final class WebAppWebView: WKWebView {
|
||||
var handleScriptMessage: (WKScriptMessage) -> Void = { _ in }
|
||||
private(set) var trustedOrigin: String?
|
||||
|
||||
var customInsets: UIEdgeInsets = .zero {
|
||||
didSet {
|
||||
|
|
@ -134,8 +151,6 @@ final class WebAppWebView: WKWebView {
|
|||
let contentController = WKUserContentController()
|
||||
|
||||
var handleScriptMessageImpl: ((WKScriptMessage) -> Void)?
|
||||
let eventProxyScript = WKUserScript(source: eventProxySource, injectionTime: .atDocumentStart, forMainFrameOnly: true)
|
||||
contentController.addUserScript(eventProxyScript)
|
||||
contentController.add(WeakGameScriptMessageHandler { message in
|
||||
handleScriptMessageImpl?(message)
|
||||
}, name: "performAction")
|
||||
|
|
@ -187,6 +202,36 @@ final class WebAppWebView: WKWebView {
|
|||
print()
|
||||
}
|
||||
|
||||
func bindTrustedOrigin(from url: URL) {
|
||||
guard self.trustedOrigin == nil else {
|
||||
return
|
||||
}
|
||||
guard let origin = normalizedOrigin(url: url) else {
|
||||
return
|
||||
}
|
||||
|
||||
self.trustedOrigin = origin
|
||||
|
||||
let eventProxyScript = WKUserScript(source: eventProxySource(trustedOrigin: origin), injectionTime: .atDocumentStart, forMainFrameOnly: true)
|
||||
self.configuration.userContentController.addUserScript(eventProxyScript)
|
||||
}
|
||||
|
||||
func isTrustedMainFrameMessage(_ message: WKScriptMessage) -> Bool {
|
||||
guard message.frameInfo.isMainFrame else {
|
||||
return false
|
||||
}
|
||||
guard let trustedOrigin = self.trustedOrigin else {
|
||||
return false
|
||||
}
|
||||
guard message.frameInfo.securityOriginString == trustedOrigin else {
|
||||
return false
|
||||
}
|
||||
if let currentOrigin = self.origin, currentOrigin != trustedOrigin {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override func didMoveToSuperview() {
|
||||
super.didMoveToSuperview()
|
||||
|
||||
|
|
@ -223,6 +268,9 @@ final class WebAppWebView: WKWebView {
|
|||
}
|
||||
|
||||
func sendEvent(name: String, data: String?) {
|
||||
guard let trustedOrigin = self.trustedOrigin, self.origin == trustedOrigin else {
|
||||
return
|
||||
}
|
||||
let script = "window.TelegramGameProxy && window.TelegramGameProxy.receiveEvent && window.TelegramGameProxy.receiveEvent(\"\(name)\", \(data ?? "null"))"
|
||||
self.evaluateJavaScript(script, completionHandler: { _, _ in
|
||||
})
|
||||
|
|
@ -279,29 +327,39 @@ final class WebAppWebView: WKWebView {
|
|||
}
|
||||
|
||||
var origin: String? {
|
||||
guard let url = self.url, let scheme = url.scheme, let host = url.host else {
|
||||
guard let url = self.url else {
|
||||
return nil
|
||||
}
|
||||
let port = url.port
|
||||
var origin = "\(scheme)://\(host)"
|
||||
if let port {
|
||||
origin += ":\(port)"
|
||||
}
|
||||
return origin
|
||||
return normalizedOrigin(url: url)
|
||||
}
|
||||
}
|
||||
|
||||
extension WKFrameInfo {
|
||||
var securityOriginString: String {
|
||||
let securityOrigin = self.securityOrigin
|
||||
var origin = ""
|
||||
origin.append(securityOrigin.protocol)
|
||||
origin.append("://")
|
||||
origin.append(securityOrigin.host)
|
||||
if securityOrigin.port != 0 {
|
||||
origin.append(":")
|
||||
origin.append("\(securityOrigin.port)")
|
||||
}
|
||||
return origin
|
||||
return normalizedOrigin(scheme: securityOrigin.protocol, host: securityOrigin.host, port: securityOrigin.port == 0 ? nil : securityOrigin.port) ?? ""
|
||||
}
|
||||
}
|
||||
|
||||
private func normalizedOrigin(url: URL) -> String? {
|
||||
return normalizedOrigin(scheme: url.scheme, host: url.host, port: url.port)
|
||||
}
|
||||
|
||||
private func normalizedOrigin(scheme: String?, host: String?, port: Int?) -> String? {
|
||||
guard let scheme = scheme?.lowercased(), !scheme.isEmpty, let host = host?.lowercased(), !host.isEmpty else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let includePort: Bool
|
||||
if let port {
|
||||
includePort = !(scheme == "http" && port == 80) && !(scheme == "https" && port == 443)
|
||||
} else {
|
||||
includePort = false
|
||||
}
|
||||
|
||||
if includePort, let port {
|
||||
return "\(scheme)://\(host):\(port)"
|
||||
} else {
|
||||
return "\(scheme)://\(host)"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue