Don't read "PIC" tags as they might be too large

This commit is contained in:
Peter 2019-08-23 02:44:09 +04:00
parent 1eb0916e25
commit 47c4ab17a3
4 changed files with 96 additions and 269 deletions

View File

@ -1229,6 +1229,9 @@ final class SharedApplicationContext {
extendNow = true
}
}
#if DEBUG
extendNow = false
#endif
sharedApplicationContext.wakeupManager.allowBackgroundTimeExtension(timeout: 4.0, extendNow: extendNow)
})
@ -1300,7 +1303,20 @@ final class SharedApplicationContext {
}
Logger.shared.log("App \(self.episodeId)", "remoteNotification: \(redactedPayload)")
completionHandler(UIBackgroundFetchResult.noData)
if userInfo["p"] == nil {
return
}
let _ = (self.sharedContextPromise.get()
|> take(1)
|> deliverOnMainQueue).start(next: { sharedApplicationContext in
sharedApplicationContext.wakeupManager.replaceCurrentExtensionWithExternalTime(completion: {
completionHandler(.newData)
}, timeout: 29.0)
sharedApplicationContext.notificationManager.addNotification(userInfo)
})
}
func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
@ -1325,261 +1341,11 @@ final class SharedApplicationContext {
if case PKPushType.voIP = type {
Logger.shared.log("App \(self.episodeId)", "pushRegistry payload: \(payload.dictionaryPayload)")
sharedApplicationContext.notificationManager.addEncryptedNotification(payload.dictionaryPayload)
sharedApplicationContext.notificationManager.addNotification(payload.dictionaryPayload)
}
})
}
/*private func processPushPayload(_ payload: [AnyHashable: Any], account: Account) {
let decryptedPayload: Signal<[AnyHashable: Any]?, NoError>
if let _ = payload["aps"] as? [AnyHashable: Any] {
decryptedPayload = .single(payload)
} else if var encryptedPayload = payload["p"] as? String {
encryptedPayload = encryptedPayload.replacingOccurrences(of: "-", with: "+")
encryptedPayload = encryptedPayload.replacingOccurrences(of: "_", with: "/")
while encryptedPayload.count % 4 != 0 {
encryptedPayload.append("=")
}
if let data = Data(base64Encoded: encryptedPayload) {
decryptedPayload = decryptedNotificationPayload(account: account, data: data)
|> map { value -> [AnyHashable: Any]? in
if let value = value, let object = try? JSONSerialization.jsonObject(with: value, options: []) {
return object as? [AnyHashable: Any]
}
return nil
}
} else {
decryptedPayload = .single(nil)
}
} else {
decryptedPayload = .single(nil)
}
let _ = (decryptedPayload
|> deliverOnMainQueue).start(next: { payload in
guard let payload = payload else {
return
}
var redactedPayload = payload
if var aps = redactedPayload["aps"] as? [AnyHashable: Any] {
if Logger.shared.redactSensitiveData {
if aps["alert"] != nil {
aps["alert"] = "[[redacted]]"
}
if aps["body"] != nil {
aps["body"] = "[[redacted]]"
}
}
redactedPayload["aps"] = aps
}
Logger.shared.log("Apns \(self.episodeId)", "\(redactedPayload)")
let aps = payload["aps"] as? [AnyHashable: Any]
if UIApplication.shared.applicationState == .background {
var readMessageId: MessageId?
var isCall = false
var isAnnouncement = false
var isLocationPolling = false
var isMutePolling = false
var title: String = ""
var body: String?
var apnsSound: String?
var configurationUpdate: (Int32, String, Int32, Data?)?
if let aps = aps, let alert = aps["alert"] as? String {
if let range = alert.range(of: ": ") {
title = String(alert[..<range.lowerBound])
body = String(alert[range.upperBound...])
} else {
body = alert
}
} else if let aps = aps, let alert = aps["alert"] as? [AnyHashable: AnyObject] {
if let alertBody = alert["body"] as? String {
body = alertBody
if let alertTitle = alert["title"] as? String {
title = alertTitle
}
}
if let locKey = alert["loc-key"] as? String {
if locKey == "PHONE_CALL_REQUEST" {
isCall = true
} else if locKey == "GEO_LIVE_PENDING" {
isLocationPolling = true
} else if locKey == "MESSAGE_MUTED" {
isMutePolling = true
}
let string = NSLocalizedString(locKey, comment: "")
if !string.isEmpty {
if let locArgs = alert["loc-args"] as? [AnyObject] {
var args: [CVarArg] = []
var failed = false
for arg in locArgs {
if let arg = arg as? CVarArg {
args.append(arg)
} else {
failed = true
break
}
}
if failed {
body = "\(string)"
} else {
body = String(format: string, arguments: args)
}
} else {
body = "\(string)"
}
} else {
body = nil
}
} else {
body = nil
}
}
if let aps = aps, let address = aps["addr"] as? String, let datacenterId = aps["dc"] as? Int {
var host = address
var port: Int32 = 443
if let range = address.range(of: ":") {
host = String(address[address.startIndex ..< range.lowerBound])
if let portValue = Int(String(address[range.upperBound...])) {
port = Int32(portValue)
}
}
var secret: Data?
if let secretString = aps["sec"] as? String {
let data = dataWithHexString(secretString)
if data.count == 16 || data.count == 32 {
secret = data
}
}
configurationUpdate = (Int32(datacenterId), host, port, secret)
}
if let aps = aps, let sound = aps["sound"] as? String {
apnsSound = sound
}
if payload["call_id"] != nil {
isCall = true
}
if payload["announcement"] != nil {
isAnnouncement = true
}
if let body = body {
if isAnnouncement {
self.queuedAnnouncements.append(body)
self.maybeDequeueAnnouncements()
} else {
var peerId: PeerId?
var notificationRequestId: NotificationManagedNotificationRequestId?
if let fromId = payload["from_id"] {
let fromIdValue = fromId as! NSString
peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: Int32(fromIdValue.intValue))
} else if let fromId = payload["chat_id"] {
let fromIdValue = fromId as! NSString
peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: Int32(fromIdValue.intValue))
} else if let fromId = payload["channel_id"] {
let fromIdValue = fromId as! NSString
peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: Int32(fromIdValue.intValue))
}
if let msgId = payload["msg_id"] {
let msgIdValue = msgId as! NSString
if let peerId = peerId {
notificationRequestId = .messageId(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(msgIdValue.intValue)))
}
} else if let randomId = payload["random_id"] {
let randomIdValue = randomId as! NSString
var peerId: PeerId?
if let encryptionIdString = payload["encryption_id"] as? String, let encryptionId = Int32(encryptionIdString) {
peerId = PeerId(namespace: Namespaces.Peer.SecretChat, id: encryptionId)
}
notificationRequestId = .globallyUniqueId(randomIdValue.longLongValue, peerId)
} else {
isMutePolling = true
}
if let notificationRequestId = notificationRequestId {
self.queuedNotificationRequests.append((title, body, apnsSound, notificationRequestId))
self.maybeDequeueNotificationRequests()
} else if isMutePolling {
self.queuedMutePolling = true
self.maybeDequeueNotificationRequests()
}
}
} else if let _ = payload["max_id"] {
var peerId: PeerId?
if let fromId = payload["from_id"] {
let fromIdValue = fromId as! NSString
peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: Int32(fromIdValue.intValue))
} else if let fromId = payload["chat_id"] {
let fromIdValue = fromId as! NSString
peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: Int32(fromIdValue.intValue))
} else if let fromId = payload["channel_id"] {
let fromIdValue = fromId as! NSString
peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: Int32(fromIdValue.intValue))
}
if let peerId = peerId {
if let msgId = payload["max_id"] {
let msgIdValue = msgId as! NSString
if msgIdValue.intValue != 0 {
readMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(msgIdValue.intValue))
}
}
}
}
var addedWakeups = Set<QueuedWakeup>()
if isCall {
addedWakeups.insert(.call)
}
if isLocationPolling {
addedWakeups.insert(.backgroundLocation)
}
if !addedWakeups.isEmpty {
self.queuedWakeups.formUnion(addedWakeups)
self.maybeDequeueWakeups()
}
if let readMessageId = readMessageId {
self.clearNotificationsManager?.append(readMessageId)
self.clearNotificationsManager?.commitNow()
let signal = self.context.get()
|> take(1)
|> mapToSignal { context -> Signal<Void, NoError> in
if let context = context {
return context.context.account.postbox.transaction (ignoreDisabled: true, { transaction -> Void in
transaction.applyIncomingReadMaxId(readMessageId)
})
} else {
return .complete()
}
}
let _ = signal.start()
}
if let (datacenterId, host, port, secret) = configurationUpdate {
let signal = self.context.get()
|> take(1)
|> mapToSignal { context -> Signal<Void, NoError> in
if let context = context {
context.context.account.network.mergeBackupDatacenterAddress(datacenterId: datacenterId, host: host, port: port, secret: secret)
}
return .complete()
}
let _ = signal.start()
}
}
})
}*/
public func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) {
Logger.shared.log("App \(self.episodeId)", "invalidated token for \(type)")
}

View File

@ -21,6 +21,14 @@ private final class PollStateContext {
}
}
private final class NotificationInfo {
let dict: [AnyHashable: Any]
init(dict: [AnyHashable: Any]) {
self.dict = dict
}
}
public final class SharedNotificationManager {
private let episodeId: UInt32
private let application: UIApplication
@ -35,7 +43,7 @@ public final class SharedNotificationManager {
private var accountsAndKeys: [(Account, Bool, MasterNotificationKey)]?
private var accountsAndKeysDisposable: Disposable?
private var encryptedNotifications: [[AnyHashable: Any]] = []
private var notifications: [NotificationInfo] = []
private var pollStateContexts: [AccountRecordId: PollStateContext] = [:]
@ -149,8 +157,8 @@ public final class SharedNotificationManager {
}
}
func addEncryptedNotification(_ dict: [AnyHashable: Any]) {
self.encryptedNotifications.append(dict)
func addNotification(_ dict: [AnyHashable: Any]) {
self.notifications.append(NotificationInfo(dict: dict))
if self.accountsAndKeys != nil {
self.process()
@ -162,8 +170,8 @@ public final class SharedNotificationManager {
return
}
var decryptedNotifications: [(Account, Bool, [AnyHashable: Any])] = []
for dict in self.encryptedNotifications {
if var encryptedPayload = dict["p"] as? String {
for notification in self.notifications {
if var encryptedPayload = notification.dict["p"] as? String {
encryptedPayload = encryptedPayload.replacingOccurrences(of: "-", with: "+")
encryptedPayload = encryptedPayload.replacingOccurrences(of: "_", with: "/")
while encryptedPayload.count % 4 != 0 {
@ -181,7 +189,7 @@ public final class SharedNotificationManager {
}
}
}
self.encryptedNotifications.removeAll()
self.notifications.removeAll()
for (account, isCurrent, payload) in decryptedNotifications {
var redactedPayload = payload
@ -206,7 +214,7 @@ public final class SharedNotificationManager {
var isAnnouncement = false
var isLocationPolling = false
var notificationRequestId: NotificationManagedNotificationRequestId?
var isMutePolling = false
var shouldPollState = false
var title: String = ""
var body: String?
var apnsSound: String?
@ -234,7 +242,7 @@ public final class SharedNotificationManager {
} else if locKey == "GEO_LIVE_PENDING" {
isLocationPolling = true
} else if locKey == "MESSAGE_MUTED" {
isMutePolling = true
shouldPollState = true
} else if locKey == "MESSAGE_DELETED" {
var peerId: PeerId?
if let fromId = payload["from_id"] {
@ -281,8 +289,6 @@ public final class SharedNotificationManager {
} else {
body = nil
}
} else {
body = nil
}
}
@ -326,6 +332,8 @@ public final class SharedNotificationManager {
} else {
var peerId: PeerId?
shouldPollState = true
if let fromId = payload["from_id"] {
let fromIdValue = fromId as! NSString
peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: Int32(fromIdValue.intValue))
@ -350,7 +358,7 @@ public final class SharedNotificationManager {
}
notificationRequestId = .globallyUniqueId(randomIdValue.longLongValue, peerId)
} else {
isMutePolling = true
shouldPollState = true
}
}
} else if let _ = payload["max_id"] {
@ -386,7 +394,7 @@ public final class SharedNotificationManager {
return
}
if notificationRequestId != nil || isMutePolling || isCall {
if notificationRequestId != nil || shouldPollState || isCall {
if !self.inForeground || !isCurrent {
self.beginPollingState(account: account)
}

View File

@ -60,6 +60,8 @@ public final class SharedWakeupManager {
private var hasActiveAudioSessionDisposable: Disposable?
private var tasksDisposable: Disposable?
private var currentTask: (UIBackgroundTaskIdentifier, Double, SwiftSignalKit.Timer)?
private var currentExternalCompletion: (() -> Void, SwiftSignalKit.Timer)?
private var currentExternalCompletionValidationTimer: SwiftSignalKit.Timer?
private var managedPausedInBackgroundPlayer: Disposable?
@ -201,8 +203,51 @@ public final class SharedWakeupManager {
}
}
func replaceCurrentExtensionWithExternalTime(completion: @escaping () -> Void, timeout: Double) {
if let (currentCompletion, timer) = self.currentExternalCompletion {
currentCompletion()
timer.invalidate()
self.currentExternalCompletion = nil
}
let timer = SwiftSignalKit.Timer(timeout: timeout - 5.0, repeat: false, completion: { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.currentExternalCompletionValidationTimer?.invalidate()
strongSelf.currentExternalCompletionValidationTimer = nil
if let (completion, timer) = strongSelf.currentExternalCompletion {
strongSelf.currentExternalCompletion = nil
timer.invalidate()
completion()
}
strongSelf.checkTasks()
}, queue: Queue.mainQueue())
self.currentExternalCompletion = (completion, timer)
timer.start()
self.currentExternalCompletionValidationTimer?.invalidate()
let validationTimer = SwiftSignalKit.Timer(timeout: 1.0, repeat: false, completion: { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.currentExternalCompletionValidationTimer?.invalidate()
strongSelf.currentExternalCompletionValidationTimer = nil
strongSelf.checkTasks()
}, queue: Queue.mainQueue())
self.currentExternalCompletionValidationTimer = validationTimer
validationTimer.start()
self.checkTasks()
}
func checkTasks() {
var hasTasksForBackgroundExtension = false
if self.inForeground || self.hasActiveAudioSession {
if let (completion, timer) = self.currentExternalCompletion {
self.currentExternalCompletion = nil
completion()
timer.invalidate()
}
if let (taskId, _, timer) = self.currentTask {
self.currentTask = nil
timer.invalidate()
@ -210,13 +255,21 @@ public final class SharedWakeupManager {
self.isInBackgroundExtension = false
}
} else {
var hasTasksForBackgroundExtension = false
for (_, _, tasks) in self.accountsAndTasks {
if !tasks.isEmpty {
hasTasksForBackgroundExtension = true
break
}
}
if !hasTasksForBackgroundExtension && self.currentExternalCompletionValidationTimer == nil {
if let (completion, timer) = self.currentExternalCompletion {
self.currentExternalCompletion = nil
completion()
timer.invalidate()
}
}
if self.activeExplicitExtensionTimer != nil {
hasTasksForBackgroundExtension = true
}
@ -265,11 +318,11 @@ public final class SharedWakeupManager {
self.isInBackgroundExtension = false
}
}
self.updateAccounts()
self.updateAccounts(hasTasks: hasTasksForBackgroundExtension)
}
private func updateAccounts() {
if self.inForeground || self.hasActiveAudioSession || self.isInBackgroundExtension || self.activeExplicitExtensionTimer != nil {
private func updateAccounts(hasTasks: Bool) {
if self.inForeground || self.hasActiveAudioSession || self.isInBackgroundExtension || (hasTasks && self.currentExternalCompletion != nil) || self.activeExplicitExtensionTimer != nil {
for (account, primary, tasks) in self.accountsAndTasks {
if (self.inForeground && primary) || !tasks.isEmpty || (self.activeExplicitExtensionTimer != nil && primary) {
account.shouldBeServiceTaskMaster.set(.single(.always))

View File

@ -791,7 +791,7 @@ typedef struct ID3v2EMFunc {
static const ID3v2EMFunc id3v2_extra_meta_funcs[] = {
{ "GEO", "GEOB", read_geobtag, free_geobtag },
{ "PIC", "APIC", read_apic, free_apic },
//{ "PIC", "APIC", read_apic, free_apic },
{ "CHAP","CHAP", read_chapter, free_chapter },
{ "PRIV","PRIV", read_priv, free_priv },
{ NULL }