mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			338 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Matlab
		
	
		
		
			
		
	
	
			338 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Matlab
		
	
| 
								 
											5 years ago
										 
									 | 
							
								#import "DataSource.h"
							 | 
						||
| 
								 | 
							
								#import "MIMETypeUtil.h"
							 | 
						||
| 
								 | 
							
								#import "NSData+Image.h"
							 | 
						||
| 
								 | 
							
								#import "OWSFileSystem.h"
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								#import <SignalCoreKit/NSString+OWS.h>
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								#import <SessionUtilitiesKit/SessionUtilitiesKit-Swift.h>
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								NS_ASSUME_NONNULL_BEGIN
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@interface DataSource ()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@property (nonatomic) BOOL shouldDeleteOnDeallocation;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// The file path for the data, if it already exists on disk.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// This method is safe to call as it will not do any expensive reads or writes.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// May return nil if the data does not (yet) reside on disk.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Use dataUrl instead if you need to access the data; it will
							 | 
						||
| 
								 | 
							
								// ensure the data is on disk and return a URL, barring an error.
							 | 
						||
| 
								 | 
							
								- (nullable NSString *)dataPathIfOnDisk;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#pragma mark -
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@implementation DataSource
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (NSData *)data
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return nil;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (nullable NSURL *)dataUrl
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return nil;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (nullable NSString *)dataPathIfOnDisk
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return nil;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (NSUInteger)dataLength
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (BOOL)writeToPath:(NSString *)dstFilePath
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return NO;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (BOOL)isValidImage
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    NSString *_Nullable dataPath = [self dataPathIfOnDisk];
							 | 
						||
| 
								 | 
							
								    if (dataPath) {
							 | 
						||
| 
								 | 
							
								        // if ows_isValidImage is given a file path, it will
							 | 
						||
| 
								 | 
							
								        // avoid loading most of the data into memory, which
							 | 
						||
| 
								 | 
							
								        // is considerably more performant, so try to do that.
							 | 
						||
| 
								 | 
							
								        return [NSData ows_isValidImageAtPath:dataPath mimeType:self.mimeType];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    NSData *data = [self data];
							 | 
						||
| 
								 | 
							
								    return [data ows_isValidImage];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (BOOL)isValidVideo
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return [OWSMediaUtils isValidVideoWithPath:self.dataUrl.path];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (void)setSourceFilename:(nullable NSString *)sourceFilename
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    _sourceFilename = sourceFilename.filterFilename;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Returns the MIME type, if known.
							 | 
						||
| 
								 | 
							
								- (nullable NSString *)mimeType
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return nil;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#pragma mark -
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@interface DataSourceValue ()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@property (nonatomic) NSData *dataValue;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@property (nonatomic) NSString *fileExtension;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// This property is lazy-populated.
							 | 
						||
| 
								 | 
							
								@property (nonatomic, nullable) NSString *cachedFilePath;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#pragma mark -
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@implementation DataSourceValue
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (void)dealloc
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (self.shouldDeleteOnDeallocation) {
							 | 
						||
| 
								 | 
							
								        NSString *_Nullable filePath = self.cachedFilePath;
							 | 
						||
| 
								 | 
							
								        if (filePath) {
							 | 
						||
| 
								 | 
							
								            dispatch_async(dispatch_get_main_queue(), ^{
							 | 
						||
| 
								 | 
							
								                NSError *error;
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								                [[NSFileManager defaultManager] removeItemAtPath:filePath error:&error];
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								            });
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								+ (nullable DataSource *)dataSourceWithData:(NSData *)data
							 | 
						||
| 
								 | 
							
								                              fileExtension:(NSString *)fileExtension
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (!data) {
							 | 
						||
| 
								 | 
							
								        return nil;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    DataSourceValue *instance = [DataSourceValue new];
							 | 
						||
| 
								 | 
							
								    instance.dataValue = data;
							 | 
						||
| 
								 | 
							
								    instance.fileExtension = fileExtension;
							 | 
						||
| 
								 | 
							
								    instance.shouldDeleteOnDeallocation = YES;
							 | 
						||
| 
								 | 
							
								    return instance;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								+ (nullable DataSource *)dataSourceWithData:(NSData *)data
							 | 
						||
| 
								 | 
							
								                                    utiType:(NSString *)utiType
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    NSString *fileExtension = [MIMETypeUtil fileExtensionForUTIType:utiType];
							 | 
						||
| 
								 | 
							
								    return [self dataSourceWithData:data fileExtension:fileExtension];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								+ (nullable DataSource *)dataSourceWithOversizeText:(NSString *_Nullable)text
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (!text) {
							 | 
						||
| 
								 | 
							
								        return nil;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    NSData *data = [text.filterStringForDisplay dataUsingEncoding:NSUTF8StringEncoding];
							 | 
						||
| 
								 | 
							
								    return [self dataSourceWithData:data fileExtension:kOversizeTextAttachmentFileExtension];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								+ (DataSource *)dataSourceWithSyncMessageData:(NSData *)data
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return [self dataSourceWithData:data fileExtension:kSyncMessageFileExtension];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								+ (DataSource *)emptyDataSource
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return [self dataSourceWithData:[NSData new] fileExtension:@"bin"];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (NSData *)data
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return self.dataValue;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (nullable NSURL *)dataUrl
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    NSString *_Nullable path = [self dataPath];
							 | 
						||
| 
								 | 
							
								    return (path ? [NSURL fileURLWithPath:path] : nil);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (nullable NSString *)dataPath
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    @synchronized(self)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (!self.cachedFilePath) {
							 | 
						||
| 
								 | 
							
								            NSString *filePath = [OWSFileSystem temporaryFilePathWithFileExtension:self.fileExtension];
							 | 
						||
| 
								 | 
							
								            if ([self writeToPath:filePath]) {
							 | 
						||
| 
								 | 
							
								                self.cachedFilePath = filePath;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return self.cachedFilePath;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (nullable NSString *)dataPathIfOnDisk
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return self.cachedFilePath;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (NSUInteger)dataLength
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return self.dataValue.length;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (BOOL)writeToPath:(NSString *)dstFilePath
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    NSData *dataCopy = self.dataValue;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    BOOL success = [dataCopy writeToFile:dstFilePath atomically:YES];
							 | 
						||
| 
								 | 
							
								    if (!success) {
							 | 
						||
| 
								 | 
							
								        return NO;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        return YES;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (nullable NSString *)mimeType
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return (self.fileExtension ? [MIMETypeUtil mimeTypeForFileExtension:self.fileExtension] : nil);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#pragma mark -
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@interface DataSourcePath ()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@property (nonatomic) NSString *filePath;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// These properties are lazy-populated.
							 | 
						||
| 
								 | 
							
								@property (nonatomic) NSData *cachedData;
							 | 
						||
| 
								 | 
							
								@property (nonatomic) NSNumber *cachedDataLength;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#pragma mark -
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@implementation DataSourcePath
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (void)dealloc
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (self.shouldDeleteOnDeallocation) {
							 | 
						||
| 
								 | 
							
								        NSString *filePath = self.filePath;
							 | 
						||
| 
								 | 
							
								        if (filePath) {
							 | 
						||
| 
								 | 
							
								            dispatch_async(dispatch_get_main_queue(), ^{
							 | 
						||
| 
								 | 
							
								                NSError *error;
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								                [[NSFileManager defaultManager] removeItemAtPath:filePath error:&error];
							 | 
						||
| 
								 
											5 years ago
										 
									 | 
							
								            });
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								+ (nullable DataSource *)dataSourceWithURL:(NSURL *)fileUrl shouldDeleteOnDeallocation:(BOOL)shouldDeleteOnDeallocation
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (!fileUrl || ![fileUrl isFileURL]) {
							 | 
						||
| 
								 | 
							
								        return nil;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    DataSourcePath *instance = [DataSourcePath new];
							 | 
						||
| 
								 | 
							
								    instance.filePath = fileUrl.path;
							 | 
						||
| 
								 | 
							
								    instance.shouldDeleteOnDeallocation = shouldDeleteOnDeallocation;
							 | 
						||
| 
								 | 
							
								    return instance;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								+ (nullable DataSource *)dataSourceWithFilePath:(NSString *)filePath
							 | 
						||
| 
								 | 
							
								                     shouldDeleteOnDeallocation:(BOOL)shouldDeleteOnDeallocation
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (!filePath) {
							 | 
						||
| 
								 | 
							
								        return nil;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    DataSourcePath *instance = [DataSourcePath new];
							 | 
						||
| 
								 | 
							
								    instance.filePath = filePath;
							 | 
						||
| 
								 | 
							
								    instance.shouldDeleteOnDeallocation = shouldDeleteOnDeallocation;
							 | 
						||
| 
								 | 
							
								    return instance;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (void)setFilePath:(NSString *)filePath
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    _filePath = filePath;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (NSData *)data
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    @synchronized(self)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (!self.cachedData) {
							 | 
						||
| 
								 | 
							
								            self.cachedData = [NSData dataWithContentsOfFile:self.filePath];
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (!self.cachedData) {
							 | 
						||
| 
								 | 
							
								            self.cachedData = [NSData new];
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return self.cachedData;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (nullable NSURL *)dataUrl
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return [NSURL fileURLWithPath:self.filePath];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (nullable NSString *)dataPath
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return self.filePath;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (nullable NSString *)dataPathIfOnDisk
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return self.filePath;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (NSUInteger)dataLength
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    @synchronized(self)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (!self.cachedDataLength) {
							 | 
						||
| 
								 | 
							
								            NSError *error;
							 | 
						||
| 
								 | 
							
								            NSDictionary<NSFileAttributeKey, id> *_Nullable attributes =
							 | 
						||
| 
								 | 
							
								                [[NSFileManager defaultManager] attributesOfItemAtPath:self.filePath error:&error];
							 | 
						||
| 
								 | 
							
								            if (!attributes || error) {
							 | 
						||
| 
								 | 
							
								                self.cachedDataLength = @(0);
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                uint64_t fileSize = [attributes fileSize];
							 | 
						||
| 
								 | 
							
								                self.cachedDataLength = @(fileSize);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return [self.cachedDataLength unsignedIntegerValue];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (BOOL)writeToPath:(NSString *)dstFilePath
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    NSError *error;
							 | 
						||
| 
								 | 
							
								    BOOL success = [[NSFileManager defaultManager] copyItemAtPath:self.filePath toPath:dstFilePath error:&error];
							 | 
						||
| 
								 | 
							
								    if (!success || error) {
							 | 
						||
| 
								 | 
							
								        return NO;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        return YES;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- (nullable NSString *)mimeType
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    NSString *_Nullable fileExtension = self.filePath.pathExtension;
							 | 
						||
| 
								 | 
							
								    return (fileExtension ? [MIMETypeUtil mimeTypeForFileExtension:fileExtension] : nil);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								NS_ASSUME_NONNULL_END
							 |