Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/ios.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormarinofaggiana <marino@marinofaggiana.com>2020-12-26 14:19:40 +0300
committermarinofaggiana <marino@marinofaggiana.com>2020-12-26 14:19:40 +0300
commit48b27fea23f77d890fba4a5572173562eecd7fb9 (patch)
treed8ef379046246d5319c2f6176edd8821bff96821 /iOSClient/PushNotification
parent0f60ef95202dcf6ed3e756a5d41cd2318993a389 (diff)
clear code [move out the push notification]
Diffstat (limited to 'iOSClient/PushNotification')
-rw-r--r--iOSClient/PushNotification/NCPushNotification.h41
-rw-r--r--iOSClient/PushNotification/NCPushNotification.m214
2 files changed, 255 insertions, 0 deletions
diff --git a/iOSClient/PushNotification/NCPushNotification.h b/iOSClient/PushNotification/NCPushNotification.h
new file mode 100644
index 000000000..ee6d8f401
--- /dev/null
+++ b/iOSClient/PushNotification/NCPushNotification.h
@@ -0,0 +1,41 @@
+//
+// NCPushNotification.h
+// Nextcloud
+//
+// Created by Marino Faggiana on 26/12/20.
+// Copyright © 2020 Marino Faggiana. All rights reserved.
+//
+// Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface NCPushNotification : NSObject
+
++ (instancetype)shared;
+@property (nonatomic, strong) NSString *pushKitToken;
+
+- (void)pushNotification;
+- (void)applicationdidReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;
+- (void)unsubscribingNextcloudServerPushNotification:(NSString *)account urlBase:(NSString *)urlBase user:(NSString *)user withSubscribing:(BOOL)subscribing;
+- (void)removeNotificationWithNotificationId:(NSInteger)notificationId usingDecryptionKey:(NSData *)key;
+- (void)registerForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOSClient/PushNotification/NCPushNotification.m b/iOSClient/PushNotification/NCPushNotification.m
new file mode 100644
index 000000000..29d2d6c1d
--- /dev/null
+++ b/iOSClient/PushNotification/NCPushNotification.m
@@ -0,0 +1,214 @@
+//
+// NCPushNotification.m
+// Nextcloud
+//
+// Created by Marino Faggiana on 26/12/20.
+// Copyright © 2020 Marino Faggiana. All rights reserved.
+//
+// Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "AppDelegate.h"
+#import "NCBridgeSwift.h"
+#import "NCPushNotification.h"
+#import "NCPushNotificationEncryption.h"
+
+@interface NCPushNotification ()
+{
+ AppDelegate *appDelegate;
+}
+@end
+
+@implementation NCPushNotification
+
++ (instancetype)shared {
+ static NCPushNotification *pushNotification = nil;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ pushNotification = [self new];
+ pushNotification->appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
+
+ });
+ return pushNotification;
+}
+
+- (void)pushNotification
+{
+ if (appDelegate.account.length == 0 || self.pushKitToken.length == 0) { return; }
+
+ for (tableAccount *result in [[NCManageDatabase shared] getAllAccount]) {
+
+ NSString *token = [CCUtility getPushNotificationToken:result.account];
+
+ if (![token isEqualToString:self.pushKitToken]) {
+ if (token != nil) {
+ // unsubscribing + subscribing
+ [self unsubscribingNextcloudServerPushNotification:result.account urlBase:result.urlBase user:result.user withSubscribing:true];
+ } else {
+ [self subscribingNextcloudServerPushNotification:result.account urlBase:result.urlBase user:result.user];
+ }
+ }
+ }
+}
+
+- (void)applicationdidReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
+
+ NSString *message = [userInfo objectForKey:@"subject"];
+ if (message) {
+ NSArray *results = [[NCManageDatabase shared] getAllAccount];
+ for (tableAccount *result in results) {
+ if ([CCUtility getPushNotificationPrivateKey:result.account]) {
+ NSData *decryptionKey = [CCUtility getPushNotificationPrivateKey:result.account];
+ NSString *decryptedMessage = [[NCPushNotificationEncryption shared] decryptPushNotification:message withDevicePrivateKey:decryptionKey];
+ if (decryptedMessage) {
+ NSData *data = [decryptedMessage dataUsingEncoding:NSUTF8StringEncoding];
+ NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
+ NSInteger nid = [[json objectForKey:@"nid"] integerValue];
+ BOOL delete = [[json objectForKey:@"delete"] boolValue];
+ BOOL deleteAll = [[json objectForKey:@"delete-all"] boolValue];
+ if (delete) {
+ [[NCPushNotification shared] removeNotificationWithNotificationId:nid usingDecryptionKey:decryptionKey];
+ } else if (deleteAll) {
+ [[NCPushNotification shared] cleanAllNotifications];
+ }
+ }
+ }
+ }
+ }
+
+ completionHandler(UIBackgroundFetchResultNoData);
+}
+
+- (void)subscribingNextcloudServerPushNotification:(NSString *)account urlBase:(NSString *)urlBase user:(NSString *)user
+{
+ if (appDelegate.account.length == 0 || self.pushKitToken.length == 0) { return; }
+
+ [[NCPushNotificationEncryption shared] generatePushNotificationsKeyPair:account];
+
+ NSString *pushTokenHash = [[NCEndToEndEncryption sharedManager] createSHA512:self.pushKitToken];
+ NSData *pushPublicKey = [CCUtility getPushNotificationPublicKey:account];
+ NSString *pushDevicePublicKey = [[NSString alloc] initWithData:pushPublicKey encoding:NSUTF8StringEncoding];
+ NSString *proxyServerPath = [NCBrandOptions shared].pushNotificationServerProxy;
+
+ [[NCCommunication shared] subscribingPushNotificationWithServerUrl:urlBase account:account user:user password:[CCUtility getPassword:account] pushTokenHash:pushTokenHash devicePublicKey:pushDevicePublicKey proxyServerUrl:proxyServerPath customUserAgent:nil addCustomHeaders:nil completionHandler:^(NSString *account, NSString *deviceIdentifier, NSString *signature, NSString *publicKey, NSInteger errorCode, NSString *errorDescription) {
+ if (errorCode == 0) {
+ NSString *userAgent = [NSString stringWithFormat:@"%@ (Strict VoIP)", [CCUtility getUserAgent]];
+ [[NCCommunication shared] subscribingPushProxyWithProxyServerUrl:proxyServerPath pushToken:self.pushKitToken deviceIdentifier:deviceIdentifier signature:signature publicKey:publicKey userAgent:userAgent completionHandler:^(NSInteger errorCode, NSString *errorDescription) {
+ if (errorCode == 0) {
+
+ [[NCCommunicationCommon shared] writeLog:@"Subscribed to Push Notification server & proxy successfully"];
+
+ [CCUtility setPushNotificationToken:account token:self.pushKitToken];
+ [CCUtility setPushNotificationDeviceIdentifier:account deviceIdentifier:deviceIdentifier];
+ [CCUtility setPushNotificationDeviceIdentifierSignature:account deviceIdentifierSignature:signature];
+ [CCUtility setPushNotificationSubscribingPublicKey:account publicKey:publicKey];
+ }
+ }];
+ }
+ }];
+}
+
+- (void)unsubscribingNextcloudServerPushNotification:(NSString *)account urlBase:(NSString *)urlBase user:(NSString *)user withSubscribing:(BOOL)subscribing
+{
+ if (appDelegate.account.length == 0) { return; }
+
+ NSString *deviceIdentifier = [CCUtility getPushNotificationDeviceIdentifier:account];
+ NSString *signature = [CCUtility getPushNotificationDeviceIdentifierSignature:account];
+ NSString *publicKey = [CCUtility getPushNotificationSubscribingPublicKey:account];
+
+ [[NCCommunication shared] unsubscribingPushNotificationWithServerUrl:urlBase account:account user:user password:[CCUtility getPassword:account] customUserAgent:nil addCustomHeaders:nil completionHandler:^(NSString *account, NSInteger errorCode, NSString *errorDescription) {
+ if (errorCode == 0) {
+ NSString *userAgent = [NSString stringWithFormat:@"%@ (Strict VoIP)", [CCUtility getUserAgent]];
+ NSString *proxyServerPath = [NCBrandOptions shared].pushNotificationServerProxy;
+ [[NCCommunication shared] unsubscribingPushProxyWithProxyServerUrl:proxyServerPath deviceIdentifier:deviceIdentifier signature:signature publicKey:publicKey userAgent:userAgent completionHandler:^(NSInteger errorCode, NSString *errorDescription) {
+ if (errorCode == 0) {
+
+ [[NCCommunicationCommon shared] writeLog:@"Unsubscribed to Push Notification server & proxy successfully."];
+
+ [CCUtility setPushNotificationPublicKey:account data:nil];
+ [CCUtility setPushNotificationSubscribingPublicKey:account publicKey:nil];
+ [CCUtility setPushNotificationPrivateKey:account data:nil];
+ [CCUtility setPushNotificationToken:account token:nil];
+ [CCUtility setPushNotificationDeviceIdentifier:account deviceIdentifier:nil];
+ [CCUtility setPushNotificationDeviceIdentifierSignature:account deviceIdentifierSignature:nil];
+
+ if (self.pushKitToken != nil && subscribing) {
+ [self subscribingNextcloudServerPushNotification:account urlBase:urlBase user:user];
+ }
+ }
+ }];
+ }
+ }];
+}
+
+- (void)cleanAllNotifications
+{
+ [[UNUserNotificationCenter currentNotificationCenter] removeAllDeliveredNotifications];
+}
+
+- (void)removeNotificationWithNotificationId:(NSInteger)notificationId usingDecryptionKey:(NSData *)key
+{
+ // Check in pending notifications
+ [[UNUserNotificationCenter currentNotificationCenter] getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> * _Nonnull requests) {
+ for (UNNotificationRequest *notificationRequest in requests) {
+ NSString *message = [notificationRequest.content.userInfo objectForKey:@"subject"];
+ NSString *decryptedMessage = [[NCPushNotificationEncryption shared] decryptPushNotification:message withDevicePrivateKey:key];
+ if (decryptedMessage) {
+ NSData *data = [decryptedMessage dataUsingEncoding:NSUTF8StringEncoding];
+ NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
+ NSInteger nid = [[json objectForKey:@"nid"] integerValue];
+ if (nid == notificationId) {
+ [[UNUserNotificationCenter currentNotificationCenter] removePendingNotificationRequestsWithIdentifiers:@[notificationRequest.identifier]];
+ }
+ }
+ }
+ }];
+ // Check in delivered notifications
+ [[UNUserNotificationCenter currentNotificationCenter] getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> * _Nonnull notifications) {
+ for (UNNotification *notification in notifications) {
+ NSString *message = [notification.request.content.userInfo objectForKey:@"subject"];
+ NSString *decryptedMessage = [[NCPushNotificationEncryption shared] decryptPushNotification:message withDevicePrivateKey:key];
+ if (decryptedMessage) {
+ NSData *data = [decryptedMessage dataUsingEncoding:NSUTF8StringEncoding];
+ NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
+ NSInteger nid = [[json objectForKey:@"nid"] integerValue];
+ if (nid == notificationId) {
+ [[UNUserNotificationCenter currentNotificationCenter] removeDeliveredNotificationsWithIdentifiers:@[notification.request.identifier]];
+ }
+ }
+ }
+ }];
+}
+
+- (void)registerForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
+{
+ self.pushKitToken = [self stringWithDeviceToken:deviceToken];
+ [self pushNotification];
+}
+
+- (NSString *)stringWithDeviceToken:(NSData *)deviceToken
+{
+ const char *data = [deviceToken bytes];
+ NSMutableString *token = [NSMutableString string];
+
+ for (NSUInteger i = 0; i < [deviceToken length]; i++) {
+ [token appendFormat:@"%02.2hhX", data[i]];
+ }
+
+ return [token copy];
+}
+
+@end