forked from Ivasoft/mattermost-mobile
301 lines
13 KiB
Objective-C
301 lines
13 KiB
Objective-C
#import "SessionManager.h"
|
|
#import "MattermostBucket.h"
|
|
|
|
@implementation SessionManager
|
|
|
|
@synthesize keyChain;
|
|
|
|
+ (instancetype)sharedSession {
|
|
static id sharedMyManager = nil;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
sharedMyManager = [[self alloc] init];
|
|
});
|
|
return sharedMyManager;
|
|
}
|
|
|
|
- (instancetype)init {
|
|
self = [super init];
|
|
if (self) {
|
|
self.bucket = [[MattermostBucket alloc] init];
|
|
self.keyChain = [[KeyChainDataSource alloc] initWithMode:KSM_Identities];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
-(void)setRequestWithGroup:(NSString *)requestWithGroup certificateName:(NSString *)certificateName {
|
|
self.requestWithGroup = requestWithGroup;
|
|
self.certificateName = certificateName;
|
|
self.isBackground = [certificateName length] == 0;
|
|
}
|
|
|
|
-(void)setDataForRequest:(NSDictionary *)data forRequestWithGroup:(NSString *)requestWithGroup {
|
|
NSString *appGroupId = [self getAppGroupIdFromRequestIdentifier:requestWithGroup];
|
|
[[self.bucket bucketByName:appGroupId] setObject:data forKey:requestWithGroup];
|
|
}
|
|
|
|
|
|
-(NSString *)getAppGroupIdFromRequestIdentifier:(NSString *) requestWithGroup {
|
|
return [requestWithGroup componentsSeparatedByString:@"|"][1];
|
|
}
|
|
|
|
-(NSDictionary *)getCredentialsForRequest:(NSString *)requestWithGroup {
|
|
NSString * appGroupId = [self getAppGroupIdFromRequestIdentifier:requestWithGroup];
|
|
NSString *entitiesString = [self.bucket readFromFile:@"entities" appGroupId:appGroupId];
|
|
NSData *entitiesData = [entitiesString dataUsingEncoding:NSUTF8StringEncoding];
|
|
NSError *error;
|
|
NSDictionary *entities = [NSJSONSerialization JSONObjectWithData:entitiesData options:NSJSONReadingMutableContainers error:&error];
|
|
if (error != nil) {
|
|
return nil;
|
|
}
|
|
return [[entities objectForKey:@"general"] objectForKey:@"credentials"];
|
|
}
|
|
|
|
-(NSDictionary *)getDataForRequest:(NSString *)requestWithGroup {
|
|
NSString *appGroupId = [self getAppGroupIdFromRequestIdentifier:requestWithGroup];
|
|
return [[self.bucket bucketByName:appGroupId] objectForKey:requestWithGroup];
|
|
}
|
|
|
|
-(NSURLSession *)createSessionForRequestRequest:(NSString *)requestWithGroup {
|
|
NSString *appGroupId = [self getAppGroupIdFromRequestIdentifier:requestWithGroup];
|
|
NSURLSessionConfiguration* config;
|
|
if (self.isBackground) {
|
|
config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:requestWithGroup];
|
|
} else {
|
|
config = [NSURLSessionConfiguration defaultSessionConfiguration];
|
|
}
|
|
|
|
config.sharedContainerIdentifier = appGroupId;
|
|
return [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
|
|
}
|
|
|
|
-(void) createPost:(NSDictionary *) post
|
|
withFiles:(NSArray *)files
|
|
credentials:(NSDictionary *) credentials
|
|
requestWithGroup:(NSString *)requestWithGroup {
|
|
NSString *serverUrl = [credentials objectForKey:@"url"];
|
|
NSString *token = [credentials objectForKey:@"token"];
|
|
NSString *channelId = [post objectForKey:@"channel_id"];
|
|
NSURLSession *session = [self createSessionForRequestRequest:requestWithGroup];
|
|
NSString *appGroupId = [self getAppGroupIdFromRequestIdentifier:requestWithGroup];
|
|
|
|
for (id file in files) {
|
|
NSURL *filePath = [NSURL fileURLWithPath:[file objectForKey:@"filePath"]];
|
|
NSString *fileName = [file objectForKey:@"filename"];
|
|
|
|
NSError *err;
|
|
NSURL *tempContainerURL = [self tempContainerURL:appGroupId];
|
|
NSURL *destinationURL = [tempContainerURL URLByAppendingPathComponent: fileName];
|
|
BOOL bVal = [[NSFileManager defaultManager] copyItemAtURL:filePath toURL:destinationURL error:&err];
|
|
|
|
NSCharacterSet *allowedCharacters = [NSCharacterSet URLQueryAllowedCharacterSet];
|
|
NSString *encodedFilename = [[file objectForKey:@"filename"] stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
|
|
NSString *url = [serverUrl stringByAppendingString:@"/api/v4/files"];
|
|
NSString *queryString = [NSString stringWithFormat:@"?channel_id=%@&filename=%@", channelId, encodedFilename];
|
|
NSURL *filesUrl = [NSURL URLWithString:[url stringByAppendingString:queryString]];
|
|
NSMutableURLRequest *uploadRequest = [NSMutableURLRequest requestWithURL:filesUrl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:120.0];
|
|
[uploadRequest setHTTPMethod:@"POST"];
|
|
[uploadRequest setValue:[@"Bearer " stringByAppendingString:token] forHTTPHeaderField:@"Authorization"];
|
|
[uploadRequest setValue:@"application/json" forHTTPHeaderField:@"Accept"];
|
|
|
|
NSURLSessionUploadTask *task = [session uploadTaskWithRequest:uploadRequest fromFile:destinationURL];
|
|
NSLog(@"Executing file request %@", fileName);
|
|
[task resume];
|
|
}
|
|
}
|
|
|
|
-(void) createPost:(NSMutableDictionary *)post
|
|
withFileIds:(NSArray *)fileIds
|
|
credentials:(NSDictionary *) credentials {
|
|
NSString *serverUrl = [credentials objectForKey:@"url"];
|
|
NSString *token = [credentials objectForKey:@"token"];
|
|
|
|
if (fileIds != nil && [fileIds count] > 0) {
|
|
[post setObject:fileIds forKey:@"file_ids"];
|
|
}
|
|
|
|
NSError *error;
|
|
NSData *postData = [NSJSONSerialization dataWithJSONObject:post options:NSJSONWritingPrettyPrinted error:&error];
|
|
|
|
if (error == nil) {
|
|
NSString* postAsString = [[NSString alloc] initWithData:postData encoding:NSUTF8StringEncoding];
|
|
|
|
NSURL *createUrl = [NSURL URLWithString:[serverUrl stringByAppendingString:@"/api/v4/posts"]];
|
|
|
|
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:createUrl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5.0];
|
|
[request setHTTPMethod:@"POST"];
|
|
[request setValue:[@"Bearer " stringByAppendingString:token] forHTTPHeaderField:@"Authorization"];
|
|
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
|
|
[request setValue:@"application/json; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
|
|
[request setHTTPBody:[postAsString dataUsingEncoding:NSUTF8StringEncoding]];
|
|
|
|
NSURLSessionConfiguration* config = [NSURLSessionConfiguration ephemeralSessionConfiguration];
|
|
NSURLSession *createSession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
|
|
NSURLSessionDataTask *createTask = [createSession dataTaskWithRequest:request];
|
|
NSLog(@"Executing post request");
|
|
[createTask resume];
|
|
self.closeExtension();
|
|
} else {
|
|
self.sendShareEvent(@"extensionPostFailed");
|
|
}
|
|
}
|
|
|
|
-(void)createPostForRequest:(NSString *)requestWithGroup {
|
|
NSDictionary *data = [self getDataForRequest:requestWithGroup];
|
|
NSDictionary *post = [data objectForKey:@"post"];
|
|
NSArray *files = [data objectForKey:@"files"];
|
|
NSDictionary *credentials = [self getCredentialsForRequest:requestWithGroup];
|
|
|
|
if (credentials == nil) {
|
|
self.sendShareEvent(@"extensionPostFailed");
|
|
return;
|
|
}
|
|
|
|
if (files != nil && [files count] > 0) {
|
|
[self createPost:post withFiles:files credentials:credentials requestWithGroup:requestWithGroup];
|
|
}
|
|
else {
|
|
[self createPost:[post mutableCopy] withFileIds:nil credentials:credentials];
|
|
}
|
|
}
|
|
|
|
-(void)sendPostRequestForId:(NSString *)requestWithGroup {
|
|
NSDictionary *data = [self getDataForRequest:requestWithGroup];
|
|
NSDictionary *credentials = [self getCredentialsForRequest:requestWithGroup];
|
|
|
|
NSMutableDictionary *post = [[data objectForKey:@"post"] mutableCopy];
|
|
NSArray *fileIds = [data objectForKey:@"file_ids"];
|
|
|
|
[self createPost:post withFileIds:fileIds credentials:credentials];
|
|
}
|
|
|
|
-(NSURL*)tempContainerURL:(NSString*)appGroupId {
|
|
NSFileManager *manager = [NSFileManager defaultManager];
|
|
NSURL *containerURL = [manager containerURLForSecurityApplicationGroupIdentifier:appGroupId];
|
|
NSURL *tempDirectoryURL = [containerURL URLByAppendingPathComponent:@"shareTempItems"];
|
|
if (![manager fileExistsAtPath:[tempDirectoryURL path]]) {
|
|
NSError *err;
|
|
[manager createDirectoryAtURL:tempDirectoryURL withIntermediateDirectories:YES attributes:nil error:&err];
|
|
if (err) {
|
|
return nil;
|
|
}
|
|
}
|
|
|
|
return tempDirectoryURL;
|
|
}
|
|
|
|
|
|
-(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
|
|
NSLog(@"completition handler from normal challenge");
|
|
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate]) {
|
|
if (self.certificateName) {
|
|
SecIdentityRef identity = [keyChain GetIdentityByName:self.certificateName];
|
|
if (identity != nil) {
|
|
SecCertificateRef certificate = NULL;
|
|
OSStatus status = SecIdentityCopyCertificate(identity, &certificate);
|
|
if (!status) {
|
|
CFArrayRef emailAddresses = NULL;
|
|
SecCertificateCopyEmailAddresses(certificate, &emailAddresses);
|
|
NSArray *emails = (NSArray *)CFBridgingRelease(emailAddresses);
|
|
CFStringRef summaryRef = SecCertificateCopySubjectSummary(certificate);
|
|
NSString *tagstr = (NSString*)CFBridgingRelease(summaryRef);
|
|
NSString *email = @"";
|
|
if ([emails count] > 0){
|
|
email = [emails objectAtIndex:0];
|
|
}
|
|
NSLog(@"completion %@ %@", tagstr, email);
|
|
const void *certs[] = {certificate};
|
|
CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);
|
|
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];
|
|
[challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
|
|
completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
|
|
NSLog(@"completion handler for certificate");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
|
|
} else {
|
|
NSLog(@"completion handler regular stuff");
|
|
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
|
|
}
|
|
}
|
|
|
|
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
|
|
NSString *requestWithGroup;
|
|
if (self.isBackground) {
|
|
requestWithGroup = [[session configuration] identifier];
|
|
} else {
|
|
requestWithGroup = self.requestWithGroup;
|
|
}
|
|
NSURL *requestUrl = [[dataTask originalRequest] URL];
|
|
|
|
if ([[requestUrl absoluteString] containsString:@"files"]) {
|
|
NSString *appGroupId = [self getAppGroupIdFromRequestIdentifier:requestWithGroup];
|
|
NSError *error;
|
|
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
|
|
if (error == nil && json != nil) {
|
|
NSArray *fileInfos = [json objectForKey:@"file_infos"];
|
|
NSDictionary *dataFromBucket = [self getDataForRequest:requestWithGroup];
|
|
NSMutableDictionary *data = [dataFromBucket mutableCopy];
|
|
NSMutableArray *fileIds = [[data objectForKey:@"file_ids"] mutableCopy];
|
|
if (fileIds == nil && data != nil) {
|
|
fileIds = [[NSMutableArray alloc] init];
|
|
}
|
|
|
|
for (id file in fileInfos) {
|
|
[fileIds addObject:[file objectForKey:@"id"]];
|
|
NSString * filename = [file objectForKey:@"name"];
|
|
NSLog(@"got file id %@ %@", [file objectForKey:@"id"], filename);
|
|
NSURL *tempContainerURL = [self tempContainerURL:appGroupId];
|
|
NSURL *destinationURL = [tempContainerURL URLByAppendingPathComponent: filename];
|
|
[[NSFileManager defaultManager] removeItemAtURL:destinationURL error:nil];
|
|
}
|
|
[data setObject:fileIds forKey:@"file_ids"];
|
|
[self setDataForRequest:data forRequestWithGroup:requestWithGroup];
|
|
} else {
|
|
self.sendShareEvent(@"extensionPostFailed");
|
|
}
|
|
}
|
|
}
|
|
|
|
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionDataTask *)task didCompleteWithError:(nullable NSError *)error {
|
|
NSString *requestWithGroup;
|
|
if (self.isBackground) {
|
|
requestWithGroup = [[session configuration] identifier];
|
|
} else {
|
|
requestWithGroup = self.requestWithGroup;
|
|
}
|
|
|
|
if(error != nil) {
|
|
NSLog(@"completition ERROR %@", [error userInfo]);
|
|
NSLog(@"invalidating session %@", requestWithGroup);
|
|
[session invalidateAndCancel];
|
|
self.sendShareEvent(@"extensionPostFailed");
|
|
} else if (requestWithGroup != nil) {
|
|
NSString *appGroupId = [self getAppGroupIdFromRequestIdentifier:requestWithGroup];
|
|
NSURL *requestUrl = [[task originalRequest] URL];
|
|
|
|
NSDictionary *data = [self getDataForRequest:requestWithGroup];
|
|
NSArray *files = [data objectForKey:@"files"];
|
|
NSMutableArray *fileIds = [data objectForKey:@"file_ids"];
|
|
|
|
if ([[requestUrl absoluteString] containsString:@"files"] &&
|
|
[files count] == [fileIds count]) {
|
|
[self sendPostRequestForId:requestWithGroup];
|
|
[[self.bucket bucketByName:appGroupId] removeObjectForKey:requestWithGroup];
|
|
}
|
|
} else {
|
|
NSLog(@"SOMETHING ELSE");
|
|
}
|
|
}
|
|
|
|
-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
|
|
if (self.savedCompletionHandler) {
|
|
self.savedCompletionHandler();
|
|
self.savedCompletionHandler = nil;
|
|
}
|
|
}
|
|
|
|
@end
|